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

Commit1a29832

Browse files
committed
Split out code into new getKeyJsonValueFromContainer()
The new function stashes its output value in a JsonbValue that can bepassed in by the caller, which enables some of them to passstack-allocated structs -- saving palloc cycles. It also allows somecallers that know they are handling a jsonb object to use this new jsonbobject-specific API, instead of going through generic containerfindJsonbValueFromContainer.Author: Nikita GlukhovDiscussion:https://postgr.es/m/7c417f90-f95f-247e-ba63-d95e39c0ad14@postgrespro.ru
1 parentdbb9aed commit1a29832

File tree

3 files changed

+113
-85
lines changed

3 files changed

+113
-85
lines changed

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

Lines changed: 93 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ static void appendKey(JsonbParseState *pstate, JsonbValue *scalarVal);
5656
staticvoidappendValue(JsonbParseState*pstate,JsonbValue*scalarVal);
5757
staticvoidappendElement(JsonbParseState*pstate,JsonbValue*scalarVal);
5858
staticintlengthCompareJsonbStringValue(constvoid*a,constvoid*b);
59+
staticintlengthCompareJsonbString(constchar*val1,intlen1,
60+
constchar*val2,intlen2);
5961
staticintlengthCompareJsonbPair(constvoid*a,constvoid*b,void*arg);
6062
staticvoiduniqueifyJsonbObject(JsonbValue*object);
6163
staticJsonbValue*pushJsonbValueScalar(JsonbParseState**pstate,
@@ -329,18 +331,16 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
329331
{
330332
JEntry*children=container->children;
331333
intcount=JsonContainerSize(container);
332-
JsonbValue*result;
333334

334335
Assert((flags& ~(JB_FARRAY |JB_FOBJECT))==0);
335336

336337
/* Quick out without a palloc cycle if object/array is empty */
337338
if (count <=0)
338339
returnNULL;
339340

340-
result=palloc(sizeof(JsonbValue));
341-
342341
if ((flags&JB_FARRAY)&&JsonContainerIsArray(container))
343342
{
343+
JsonbValue*result=palloc(sizeof(JsonbValue));
344344
char*base_addr= (char*) (children+count);
345345
uint32offset=0;
346346
inti;
@@ -357,56 +357,90 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
357357

358358
JBE_ADVANCE_OFFSET(offset,children[i]);
359359
}
360+
361+
pfree(result);
360362
}
361363
elseif ((flags&JB_FOBJECT)&&JsonContainerIsObject(container))
362364
{
363-
/* Since this is an object, account for *Pairs* of Jentrys */
364-
char*base_addr= (char*) (children+count*2);
365-
uint32stopLow=0,
366-
stopHigh=count;
367-
368365
/* Object key passed by caller must be a string */
369366
Assert(key->type==jbvString);
370367

371-
/* Binary search on object/pair keys *only* */
372-
while (stopLow<stopHigh)
373-
{
374-
uint32stopMiddle;
375-
intdifference;
376-
JsonbValuecandidate;
368+
returngetKeyJsonValueFromContainer(container,key->val.string.val,
369+
key->val.string.len,NULL);
370+
}
371+
372+
/* Not found */
373+
returnNULL;
374+
}
375+
376+
/*
377+
* Find value by key in Jsonb object and fetch it into 'res', which is also
378+
* returned.
379+
*
380+
* 'res' can be passed in as NULL, in which case it's newly palloc'ed here.
381+
*/
382+
JsonbValue*
383+
getKeyJsonValueFromContainer(JsonbContainer*container,
384+
constchar*keyVal,intkeyLen,JsonbValue*res)
385+
{
386+
JEntry*children=container->children;
387+
intcount=JsonContainerSize(container);
388+
char*baseAddr;
389+
uint32stopLow,
390+
stopHigh;
377391

378-
stopMiddle=stopLow+ (stopHigh-stopLow) /2;
392+
Assert(JsonContainerIsObject(container));
379393

380-
candidate.type=jbvString;
381-
candidate.val.string.val=
382-
base_addr+getJsonbOffset(container,stopMiddle);
383-
candidate.val.string.len=getJsonbLength(container,stopMiddle);
394+
/* Quick out without a palloc cycle if object is empty */
395+
if (count <=0)
396+
returnNULL;
384397

385-
difference=lengthCompareJsonbStringValue(&candidate,key);
398+
/*
399+
* Binary search the container. Since we know this is an object, account
400+
* for *Pairs* of Jentrys
401+
*/
402+
baseAddr= (char*) (children+count*2);
403+
stopLow=0;
404+
stopHigh=count;
405+
while (stopLow<stopHigh)
406+
{
407+
uint32stopMiddle;
408+
intdifference;
409+
constchar*candidateVal;
410+
intcandidateLen;
386411

387-
if (difference==0)
388-
{
389-
/* Found our key, return corresponding value */
390-
intindex=stopMiddle+count;
412+
stopMiddle=stopLow+ (stopHigh-stopLow) /2;
391413

392-
fillJsonbValue(container,index,base_addr,
393-
getJsonbOffset(container,index),
394-
result);
414+
candidateVal=baseAddr+getJsonbOffset(container,stopMiddle);
415+
candidateLen=getJsonbLength(container,stopMiddle);
395416

396-
returnresult;
397-
}
417+
difference=lengthCompareJsonbString(candidateVal,candidateLen,
418+
keyVal,keyLen);
419+
420+
if (difference==0)
421+
{
422+
/* Found our key, return corresponding value */
423+
intindex=stopMiddle+count;
424+
425+
if (!res)
426+
res=palloc(sizeof(JsonbValue));
427+
428+
fillJsonbValue(container,index,baseAddr,
429+
getJsonbOffset(container,index),
430+
res);
431+
432+
returnres;
433+
}
434+
else
435+
{
436+
if (difference<0)
437+
stopLow=stopMiddle+1;
398438
else
399-
{
400-
if (difference<0)
401-
stopLow=stopMiddle+1;
402-
else
403-
stopHigh=stopMiddle;
404-
}
439+
stopHigh=stopMiddle;
405440
}
406441
}
407442

408443
/* Not found */
409-
pfree(result);
410444
returnNULL;
411445
}
412446

@@ -1009,6 +1043,7 @@ JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
10091043
for (;;)
10101044
{
10111045
JsonbValue*lhsVal;/* lhsVal is from pair in lhs object */
1046+
JsonbValuelhsValBuf;
10121047

10131048
rcont=JsonbIteratorNext(mContained,&vcontained, false);
10141049

@@ -1021,12 +1056,14 @@ JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
10211056
return true;
10221057

10231058
Assert(rcont==WJB_KEY);
1059+
Assert(vcontained.type==jbvString);
10241060

10251061
/* First, find value by key... */
1026-
lhsVal=findJsonbValueFromContainer((*val)->container,
1027-
JB_FOBJECT,
1028-
&vcontained);
1029-
1062+
lhsVal=
1063+
getKeyJsonValueFromContainer((*val)->container,
1064+
vcontained.val.string.val,
1065+
vcontained.val.string.len,
1066+
&lhsValBuf);
10301067
if (!lhsVal)
10311068
return false;
10321069

@@ -1771,21 +1808,27 @@ lengthCompareJsonbStringValue(const void *a, const void *b)
17711808
{
17721809
constJsonbValue*va= (constJsonbValue*)a;
17731810
constJsonbValue*vb= (constJsonbValue*)b;
1774-
intres;
17751811

17761812
Assert(va->type==jbvString);
17771813
Assert(vb->type==jbvString);
17781814

1779-
if (va->val.string.len==vb->val.string.len)
1780-
{
1781-
res=memcmp(va->val.string.val,vb->val.string.val,va->val.string.len);
1782-
}
1783-
else
1784-
{
1785-
res= (va->val.string.len>vb->val.string.len) ?1 :-1;
1786-
}
1815+
returnlengthCompareJsonbString(va->val.string.val,va->val.string.len,
1816+
vb->val.string.val,vb->val.string.len);
1817+
}
17871818

1788-
returnres;
1819+
/*
1820+
* Subroutine for lengthCompareJsonbStringValue
1821+
*
1822+
* This is also useful separately to implement binary search on
1823+
* JsonbContainers.
1824+
*/
1825+
staticint
1826+
lengthCompareJsonbString(constchar*val1,intlen1,constchar*val2,intlen2)
1827+
{
1828+
if (len1==len2)
1829+
returnmemcmp(val1,val2,len1);
1830+
else
1831+
returnlen1>len2 ?1 :-1;
17891832
}
17901833

17911834
/*

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

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -454,12 +454,6 @@ static Datum populate_array(ArrayIOData *aio, const char *colname,
454454
staticDatumpopulate_domain(DomainIOData*io,Oidtypid,constchar*colname,
455455
MemoryContextmcxt,JsValue*jsv,boolisnull);
456456

457-
/* Worker that takes care of common setup for us */
458-
staticJsonbValue*findJsonbValueFromContainerLen(JsonbContainer*container,
459-
uint32flags,
460-
char*key,
461-
uint32keylen);
462-
463457
/* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
464458
staticJsonbValue*IteratorConcat(JsonbIterator**it1,JsonbIterator**it2,
465459
JsonbParseState**state);
@@ -718,13 +712,15 @@ jsonb_object_field(PG_FUNCTION_ARGS)
718712
Jsonb*jb=PG_GETARG_JSONB_P(0);
719713
text*key=PG_GETARG_TEXT_PP(1);
720714
JsonbValue*v;
715+
JsonbValuevbuf;
721716

722717
if (!JB_ROOT_IS_OBJECT(jb))
723718
PG_RETURN_NULL();
724719

725-
v=findJsonbValueFromContainerLen(&jb->root,JB_FOBJECT,
726-
VARDATA_ANY(key),
727-
VARSIZE_ANY_EXHDR(key));
720+
v=getKeyJsonValueFromContainer(&jb->root,
721+
VARDATA_ANY(key),
722+
VARSIZE_ANY_EXHDR(key),
723+
&vbuf);
728724

729725
if (v!=NULL)
730726
PG_RETURN_JSONB_P(JsonbValueToJsonb(v));
@@ -754,14 +750,15 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
754750
Jsonb*jb=PG_GETARG_JSONB_P(0);
755751
text*key=PG_GETARG_TEXT_PP(1);
756752
JsonbValue*v;
753+
JsonbValuevbuf;
757754

758755
if (!JB_ROOT_IS_OBJECT(jb))
759756
PG_RETURN_NULL();
760757

761-
v=findJsonbValueFromContainerLen(&jb->root,JB_FOBJECT,
762-
VARDATA_ANY(key),
763-
VARSIZE_ANY_EXHDR(key));
764-
758+
v=getKeyJsonValueFromContainer(&jb->root,
759+
VARDATA_ANY(key),
760+
VARSIZE_ANY_EXHDR(key),
761+
&vbuf);
765762

766763
if (v!=NULL&&v->type!=jbvNull)
767764
PG_RETURN_TEXT_P(JsonbValueAsText(v));
@@ -1336,6 +1333,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
13361333
boolhave_object= false,
13371334
have_array= false;
13381335
JsonbValue*jbvp=NULL;
1336+
JsonbValuejbvbuf;
13391337
JsonbContainer*container;
13401338

13411339
/*
@@ -1393,10 +1391,10 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
13931391
{
13941392
if (have_object)
13951393
{
1396-
jbvp=findJsonbValueFromContainerLen(container,
1397-
JB_FOBJECT,
1398-
VARDATA(pathtext[i]),
1399-
VARSIZE(pathtext[i])-VARHDRSZ);
1394+
jbvp=getKeyJsonValueFromContainer(container,
1395+
VARDATA(pathtext[i]),
1396+
VARSIZE(pathtext[i])-VARHDRSZ,
1397+
&jbvbuf);
14001398
}
14011399
elseif (have_array)
14021400
{
@@ -3023,8 +3021,8 @@ JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
30233021
else
30243022
{
30253023
jsv->val.jsonb= !obj->val.jsonb_cont ?NULL :
3026-
findJsonbValueFromContainerLen(obj->val.jsonb_cont,JB_FOBJECT,
3027-
field,strlen(field));
3024+
getKeyJsonValueFromContainer(obj->val.jsonb_cont,field,strlen(field),
3025+
NULL);
30283026

30293027
returnjsv->val.jsonb!=NULL;
30303028
}
@@ -3848,22 +3846,6 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
38483846
}
38493847
}
38503848

3851-
/*
3852-
* findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
3853-
*/
3854-
staticJsonbValue*
3855-
findJsonbValueFromContainerLen(JsonbContainer*container,uint32flags,
3856-
char*key,uint32keylen)
3857-
{
3858-
JsonbValuek;
3859-
3860-
k.type=jbvString;
3861-
k.val.string.val=key;
3862-
k.val.string.len=keylen;
3863-
3864-
returnfindJsonbValueFromContainer(container,flags,&k);
3865-
}
3866-
38673849
/*
38683850
* Semantic actions for json_strip_nulls.
38693851
*

‎src/include/utils/jsonb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ extern intcompareJsonbContainers(JsonbContainer *a, JsonbContainer *b);
364364
externJsonbValue*findJsonbValueFromContainer(JsonbContainer*sheader,
365365
uint32flags,
366366
JsonbValue*key);
367+
externJsonbValue*getKeyJsonValueFromContainer(JsonbContainer*container,
368+
constchar*keyVal,intkeyLen,
369+
JsonbValue*res);
367370
externJsonbValue*getIthJsonbValueFromContainer(JsonbContainer*sheader,
368371
uint32i);
369372
externJsonbValue*pushJsonbValue(JsonbParseState**pstate,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp