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

Commitf9cd4d8

Browse files
author
Nikita Glukhov
committed
Refactor JsonbDeepContains()
1 parentf94e8c6 commitf9cd4d8

File tree

3 files changed

+81
-110
lines changed

3 files changed

+81
-110
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(0);
117117
Jsonb*tmpl=PG_GETARG_JSONB(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(0);
136130
Jsonb*val=PG_GETARG_JSONB(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: 78 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,12 +1152,11 @@ JsonbIteratorInit(JsonContainer *cont)
11521152
*/
11531153

11541154
bool
1155-
JsonbDeepContains(JsonIterator**val,JsonIterator**mContained)
1155+
JsonbDeepContains(JsonContainer*cval,JsonContainer*ccont)
11561156
{
1157-
JsonbValuevval,
1158-
vcontained;
1159-
JsonbIteratorTokenrval,
1160-
rcont;
1157+
JsonIterator*icont;
1158+
JsonbValuevcont;
1159+
JsonbIteratorTokenrcont;
11611160

11621161
/*
11631162
* Guard against stack overflow due to overly complex Jsonb.
@@ -1167,57 +1166,46 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
11671166
*/
11681167
check_stack_depth();
11691168

1170-
rval=JsonIteratorNext(val,&vval, false);
1171-
rcont=JsonIteratorNext(mContained,&vcontained, false);
1172-
1173-
if (rval!=rcont)
1169+
if (JsonContainerIsObject(cval)!=JsonContainerIsObject(ccont))
11741170
{
11751171
/*
11761172
* The differing return values can immediately be taken as indicating
11771173
* two differing container types at this nesting level, which is
11781174
* sufficient reason to give up entirely (but it should be the case
11791175
* that they're both some container type).
11801176
*/
1181-
Assert(rval==WJB_BEGIN_OBJECT||rval==WJB_BEGIN_ARRAY);
1182-
Assert(rcont==WJB_BEGIN_OBJECT||rcont==WJB_BEGIN_ARRAY);
11831177
return false;
11841178
}
1185-
elseif (rcont==WJB_BEGIN_OBJECT)
1179+
elseif (JsonContainerIsObject(cval))
11861180
{
1187-
Assert(vval.type==jbvObject);
1188-
Assert(vcontained.type==jbvObject);
1189-
11901181
/*
11911182
* If the lhs has fewer pairs than the rhs, it can't possibly contain
11921183
* the rhs. (This conclusion is safe only because we de-duplicate
11931184
* keys in all Jsonb objects; thus there can be no corresponding
11941185
* optimization in the array case.) The case probably won't arise
11951186
* often, but since it's such a cheap check we may as well make it.
11961187
*/
1197-
if (vval.val.object.nPairs<vcontained.val.object.nPairs)
1188+
if (JsonContainerSize(cval) >=0&&
1189+
JsonContainerSize(ccont) >=0&&
1190+
JsonContainerSize(cval)<JsonContainerSize(ccont))
11981191
return false;
11991192

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

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

12221210
if (!lhsVal)
12231211
return false;
@@ -1226,34 +1214,27 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
12261214
* ...at this stage it is apparent that there is at least a key
12271215
* match for this rhs pair.
12281216
*/
1229-
rcont=JsonIteratorNext(mContained,&vcontained, true);
1230-
1217+
rcont=JsonIteratorNext(&icont,&vcont, true);
12311218
Assert(rcont==WJB_VALUE);
12321219

12331220
/*
12341221
* Compare rhs pair's value with lhs pair's value just found using
12351222
* key
12361223
*/
1237-
if (lhsVal->type!=vcontained.type)
1224+
if (lhsVal->type!=vcont.type)
12381225
{
12391226
return false;
12401227
}
12411228
elseif (IsAJsonbScalar(lhsVal))
12421229
{
1243-
if (!equalsJsonbScalarValue(lhsVal,&vcontained))
1230+
if (!equalsJsonbScalarValue(lhsVal,&vcont))
12441231
return false;
12451232
}
12461233
else
12471234
{
12481235
/* Nested container value (object or array) */
1249-
JsonIterator*nestval,
1250-
*nestContained;
1251-
12521236
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);
12571238

12581239
/*
12591240
* Match "value" side of rhs datum object's pair recursively.
@@ -1275,18 +1256,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
12751256
* of containment (plus of course the mapped nodes must be
12761257
* equal).
12771258
*/
1278-
if (!JsonbDeepContains(&nestval,&nestContained))
1259+
if (!JsonbDeepContains(lhsVal->val.binary.data,
1260+
vcont.val.binary.data))
12791261
return false;
12801262
}
12811263
}
1264+
1265+
Assert(rcont==WJB_END_OBJECT);
1266+
Assert(icont==NULL);
12821267
}
1283-
elseif (rcont==WJB_BEGIN_ARRAY)
1268+
else
12841269
{
1285-
JsonbValue*lhsConts=NULL;
1286-
uint32nLhsElems=vval.val.array.nElems;
1287-
1288-
Assert(vval.type==jbvArray);
1289-
Assert(vcontained.type==jbvArray);
1270+
JsonbValue*lhsConts=NULL;
1271+
uint32nLhsElems=JsonContainerSize(cval);
12901272

12911273
/*
12921274
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1298,29 +1280,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
12981280
* only contain pairs, never raw scalars (a pair is represented by an
12991281
* rhs object argument with a single contained pair).
13001282
*/
1301-
if (vval.val.array.rawScalar&& !vcontained.val.array.rawScalar)
1283+
if (JsonContainerIsScalar(cval)&& !JsonContainerIsScalar(ccont))
13021284
return false;
13031285

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

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))
13201300
{
1321-
if (!findJsonbValueFromContainer((*val)->container,
1322-
JB_FARRAY,
1323-
&vcontained))
1301+
if (!findJsonbValueFromContainer(cval,JB_FARRAY,&vcont))
13241302
return false;
13251303
}
13261304
else
@@ -1333,21 +1311,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13331311
*/
13341312
if (lhsConts==NULL)
13351313
{
1336-
uint32j=0;
1314+
uint32j=0;
1315+
JsonIterator*ival;
1316+
JsonbValuevval;
1317+
1318+
if ((int32)nLhsElems<0)
1319+
nLhsElems=JsonGetArraySize(cval);
1320+
1321+
if (nLhsElems==0)
1322+
return false;
13371323

13381324
/* Make room for all possible values */
13391325
lhsConts=palloc(sizeof(JsonbValue)*nLhsElems);
13401326

1327+
ival=JsonIteratorInit(cval);
1328+
rcont=JsonIteratorNext(&ival,&vval, true);
1329+
Assert(rcont==WJB_BEGIN_ARRAY);
1330+
13411331
for (i=0;i<nLhsElems;i++)
13421332
{
13431333
/* Store all lhs elements in temp array */
1344-
rcont=JsonIteratorNext(val,&vval, true);
1334+
rcont=JsonIteratorNext(&ival,&vval, true);
13451335
Assert(rcont==WJB_ELEM);
13461336

13471337
if (vval.type==jbvBinary)
13481338
lhsConts[j++]=vval;
13491339
}
13501340

1341+
rcont=JsonIteratorNext(&ival,&vval, true);
1342+
Assert(rcont==WJB_END_ARRAY);
1343+
Assert(ival==NULL);
1344+
13511345
/* No container elements in temp array, so give up now */
13521346
if (j==0)
13531347
return false;
@@ -1360,20 +1354,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13601354
for (i=0;i<nLhsElems;i++)
13611355
{
13621356
/* Nested container value (object or array) */
1363-
JsonIterator*nestval,
1364-
*nestContained;
1365-
boolcontains;
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))
13771359
break;
13781360
}
13791361

@@ -1385,14 +1367,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13851367
return false;
13861368
}
13871369
}
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);
13921376
}
13931377

1394-
elog(ERROR,"unexpectedly fell off end of jsonb container");
1395-
return false;
1378+
return true;
13961379
}
13971380

13981381
/*

‎src/include/utils/json_generic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ extern JsonContainer *JsonValueToContainer(const JsonValue *val);
268268

269269
externintJsonCompareContainers(JsonContainer*a,JsonContainer*b);
270270

271-
externboolJsonbDeepContains(JsonIterator**val,JsonIterator**mContained);
271+
externboolJsonbDeepContains(JsonContainer*val,JsonContainer*mContained);
272272

273273
externJsonValue*JsonContainerExtractKeys(JsonContainer*jsc);
274274

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp