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

Commit61af37e

Browse files
author
Nikita Glukhov
committed
Refactor JsonbDeepContains()
1 parent5ea18ce commit61af37e

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
@@ -1180,12 +1180,11 @@ JsonbIteratorInit(JsonContainer *cont)
11801180
*/
11811181

11821182
bool
1183-
JsonbDeepContains(JsonIterator**val,JsonIterator**mContained)
1183+
JsonbDeepContains(JsonContainer*cval,JsonContainer*ccont)
11841184
{
1185-
JsonbValuevval,
1186-
vcontained;
1187-
JsonbIteratorTokenrval,
1188-
rcont;
1185+
JsonIterator*icont;
1186+
JsonbValuevcont;
1187+
JsonbIteratorTokenrcont;
11891188

11901189
/*
11911190
* Guard against stack overflow due to overly complex Jsonb.
@@ -1195,94 +1194,76 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
11951194
*/
11961195
check_stack_depth();
11971196

1198-
rval=JsonIteratorNext(val,&vval, false);
1199-
rcont=JsonIteratorNext(mContained,&vcontained, false);
1200-
1201-
if (rval!=rcont)
1197+
if (JsonContainerIsObject(cval)!=JsonContainerIsObject(ccont))
12021198
{
12031199
/*
12041200
* The differing return values can immediately be taken as indicating
12051201
* two differing container types at this nesting level, which is
12061202
* sufficient reason to give up entirely (but it should be the case
12071203
* that they're both some container type).
12081204
*/
1209-
Assert(rval==WJB_BEGIN_OBJECT||rval==WJB_BEGIN_ARRAY);
1210-
Assert(rcont==WJB_BEGIN_OBJECT||rcont==WJB_BEGIN_ARRAY);
12111205
return false;
12121206
}
1213-
elseif (rcont==WJB_BEGIN_OBJECT)
1207+
elseif (JsonContainerIsObject(cval))
12141208
{
1215-
Assert(vval.type==jbvObject);
1216-
Assert(vcontained.type==jbvObject);
1217-
12181209
/*
12191210
* If the lhs has fewer pairs than the rhs, it can't possibly contain
12201211
* the rhs. (This conclusion is safe only because we de-duplicate
12211212
* keys in all Jsonb objects; thus there can be no corresponding
12221213
* optimization in the array case.) The case probably won't arise
12231214
* often, but since it's such a cheap check we may as well make it.
12241215
*/
1225-
if (vval.val.object.nPairs<vcontained.val.object.nPairs)
1216+
if (JsonContainerSize(cval) >=0&&
1217+
JsonContainerSize(ccont) >=0&&
1218+
JsonContainerSize(cval)<JsonContainerSize(ccont))
12261219
return false;
12271220

1228-
/* Work through rhs "is it contained within?" object */
1229-
for (;;)
1230-
{
1231-
JsonbValue*lhsVal;/* lhsVal is from pair in lhs object */
1232-
JsonbValuelhsValBuf;
1233-
1234-
rcont=JsonIteratorNext(mContained,&vcontained, false);
1221+
icont=JsonIteratorInit(ccont);
1222+
rcont=JsonIteratorNext(&icont,&vcont, false);
1223+
Assert(rcont==WJB_BEGIN_OBJECT);
12351224

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

1247-
/* First, find value by key... */
1248-
lhsVal=JsonFindKeyInObject((*val)->container,
1249-
vcontained.val.string.val,
1250-
vcontained.val.string.len);
12511239
if (!lhsVal)
12521240
return false;
12531241

12541242
/*
12551243
* ...at this stage it is apparent that there is at least a key
12561244
* match for this rhs pair.
12571245
*/
1258-
rcont=JsonIteratorNext(mContained,&vcontained, true);
1259-
1246+
rcont=JsonIteratorNext(&icont,&vcont, true);
12601247
Assert(rcont==WJB_VALUE);
12611248

12621249
/*
12631250
* Compare rhs pair's value with lhs pair's value just found using
12641251
* key
12651252
*/
1266-
if (lhsVal->type!=vcontained.type)
1253+
if (lhsVal->type!=vcont.type)
12671254
{
12681255
return false;
12691256
}
12701257
elseif (IsAJsonbScalar(lhsVal))
12711258
{
1272-
if (!equalsJsonbScalarValue(lhsVal,&vcontained))
1259+
if (!equalsJsonbScalarValue(lhsVal,&vcont))
12731260
return false;
12741261
}
12751262
else
12761263
{
12771264
/* Nested container value (object or array) */
1278-
JsonIterator*nestval,
1279-
*nestContained;
1280-
12811265
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);
12861267

12871268
/*
12881269
* Match "value" side of rhs datum object's pair recursively.
@@ -1304,18 +1285,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13041285
* of containment (plus of course the mapped nodes must be
13051286
* equal).
13061287
*/
1307-
if (!JsonbDeepContains(&nestval,&nestContained))
1288+
if (!JsonbDeepContains(lhsVal->val.binary.data,
1289+
vcont.val.binary.data))
13081290
return false;
13091291
}
13101292
}
1293+
1294+
Assert(rcont==WJB_END_OBJECT);
1295+
Assert(icont==NULL);
13111296
}
1312-
elseif (rcont==WJB_BEGIN_ARRAY)
1297+
else
13131298
{
1314-
JsonbValue*lhsConts=NULL;
1315-
uint32nLhsElems=vval.val.array.nElems;
1316-
1317-
Assert(vval.type==jbvArray);
1318-
Assert(vcontained.type==jbvArray);
1299+
JsonbValue*lhsConts=NULL;
1300+
uint32nLhsElems=JsonContainerSize(cval);
13191301

13201302
/*
13211303
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1327,29 +1309,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13271309
* only contain pairs, never raw scalars (a pair is represented by an
13281310
* rhs object argument with a single contained pair).
13291311
*/
1330-
if (vval.val.array.rawScalar&& !vcontained.val.array.rawScalar)
1312+
if (JsonContainerIsScalar(cval)&& !JsonContainerIsScalar(ccont))
13311313
return false;
13321314

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

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))
13491329
{
1350-
if (!findJsonbValueFromContainer((*val)->container,
1351-
JB_FARRAY,
1352-
&vcontained))
1330+
if (!findJsonbValueFromContainer(cval,JB_FARRAY,&vcont))
13531331
return false;
13541332
}
13551333
else
@@ -1362,21 +1340,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13621340
*/
13631341
if (lhsConts==NULL)
13641342
{
1365-
uint32j=0;
1343+
uint32j=0;
1344+
JsonIterator*ival;
1345+
JsonbValuevval;
1346+
1347+
if ((int32)nLhsElems<0)
1348+
nLhsElems=JsonGetArraySize(cval);
1349+
1350+
if (nLhsElems==0)
1351+
return false;
13661352

13671353
/* Make room for all possible values */
13681354
lhsConts=palloc(sizeof(JsonbValue)*nLhsElems);
13691355

1356+
ival=JsonIteratorInit(cval);
1357+
rcont=JsonIteratorNext(&ival,&vval, true);
1358+
Assert(rcont==WJB_BEGIN_ARRAY);
1359+
13701360
for (i=0;i<nLhsElems;i++)
13711361
{
13721362
/* Store all lhs elements in temp array */
1373-
rcont=JsonIteratorNext(val,&vval, true);
1363+
rcont=JsonIteratorNext(&ival,&vval, true);
13741364
Assert(rcont==WJB_ELEM);
13751365

13761366
if (vval.type==jbvBinary)
13771367
lhsConts[j++]=vval;
13781368
}
13791369

1370+
rcont=JsonIteratorNext(&ival,&vval, true);
1371+
Assert(rcont==WJB_END_ARRAY);
1372+
Assert(ival==NULL);
1373+
13801374
/* No container elements in temp array, so give up now */
13811375
if (j==0)
13821376
return false;
@@ -1389,20 +1383,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13891383
for (i=0;i<nLhsElems;i++)
13901384
{
13911385
/* Nested container value (object or array) */
1392-
JsonIterator*nestval,
1393-
*nestContained;
1394-
boolcontains;
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))
14061388
break;
14071389
}
14081390

@@ -1414,14 +1396,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14141396
return false;
14151397
}
14161398
}
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);
14211405
}
14221406

1423-
elog(ERROR,"unexpectedly fell off end of jsonb container");
1424-
return false;
1407+
return true;
14251408
}
14261409

14271410
/*

‎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