Skip to content

Commit c9adab6

Browse files
author
Nikita Glukhov
committed
Change setPath() newval argument type from Jsonb * to JsonbValue *
Removed addJsonbToParseState() Added JsonbToJsonbValue() Added scalar jsonb unpacking in pushJsonbValue()
1 parent e267b3f commit c9adab6

File tree

3 files changed

+65
-86
lines changed

3 files changed

+65
-86
lines changed

src/backend/utils/adt/jsonb_util.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ static JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
6161
JsonbIteratorToken seq,
6262
JsonbValue *scalarVal);
6363

64+
JsonbValue *
65+
JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
66+
{
67+
if (!val)
68+
val = (JsonbValue *) palloc(sizeof(JsonbValue));
69+
70+
val->type = jbvBinary;
71+
val->val.binary.data = &jsonb->root;
72+
val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
73+
74+
return val;
75+
}
76+
6477
/*
6578
* Turn an in-memory JsonbValue into a Jsonb for on-disk storage.
6679
*
@@ -530,9 +543,30 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
530543

531544
/* unpack the binary and add each piece to the pstate */
532545
it = JsonbIteratorInit(jbval->val.binary.data);
546+
547+
if ((jbval->val.binary.data->header & JB_FSCALAR) && *pstate)
548+
{
549+
tok = JsonbIteratorNext(&it, &v, true);
550+
Assert(tok == WJB_BEGIN_ARRAY);
551+
Assert(v.type == jbvArray && v.val.array.rawScalar);
552+
553+
tok = JsonbIteratorNext(&it, &v, true);
554+
Assert(tok == WJB_ELEM);
555+
556+
res = pushJsonbValueScalar(pstate, seq, &v);
557+
558+
tok = JsonbIteratorNext(&it, &v, true);
559+
Assert(tok == WJB_END_ARRAY);
560+
Assert(it == NULL);
561+
562+
return res;
563+
}
564+
533565
while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
534566
res = pushJsonbValueScalar(pstate, tok,
535-
tok < WJB_BEGIN_ARRAY ? &v : NULL);
567+
tok < WJB_BEGIN_ARRAY ||
568+
(tok == WJB_BEGIN_ARRAY &&
569+
v.val.array.rawScalar) ? &v : NULL);
536570

537571
return res;
538572
}

src/backend/utils/adt/jsonfuncs.c

Lines changed: 29 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@
3535
#include "utils/typcache.h"
3636
#include "parser/parse_node.h"
3737

38-
#define add_newval(state, newval, unpacked) \
39-
if (unpacked) \
40-
(void) pushJsonbValue(st, WJB_VALUE, (JsonbValue *)newval); \
41-
else \
42-
addJsonbToParseState(st, (Jsonb *)newval);
43-
4438
/* Operations available for setPath */
4539
#define JB_PATH_NOOP 0x0000
4640
#define JB_PATH_CREATE 0x0001
@@ -148,17 +142,13 @@ static Datum jsonb_set_element(Datum datum, text **path, int path_len, Datum sou
148142
static Datum jsonb_get_element(Datum datum, text **path, int path_len, bool *isNull);
149143
static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
150144
bool *path_nulls, int path_len,
151-
JsonbParseState **st, int level, Jsonb *newval,
152-
bool unpacked, int op_type);
145+
JsonbParseState **st, int level, JsonbValue *newval, int op_type);
153146
static void setPathObject(JsonbIterator **it, Datum *path_elems,
154147
bool *path_nulls, int path_len, JsonbParseState **st,
155-
int level,
156-
Jsonb *newval, bool unpacked, uint32 npairs, int op_type);
148+
int level, JsonbValue *newval, uint32 npairs, int op_type);
157149
static void setPathArray(JsonbIterator **it, Datum *path_elems,
158150
bool *path_nulls, int path_len, JsonbParseState **st,
159-
int level,
160-
Jsonb *newval, bool unpacked, uint32 nelems, int op_type);
161-
static void addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb);
151+
int level, JsonbValue *newval, uint32 nelems, int op_type);
162152
static Datum jsonb_subscription_evaluate(PG_FUNCTION_ARGS);
163153
static Datum jsonb_subscription_prepare(PG_FUNCTION_ARGS);
164154

@@ -3298,57 +3288,6 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS)
32983288
PG_RETURN_POINTER(JsonbValueToJsonb(res));
32993289
}
33003290

3301-
/*
3302-
* Add values from the jsonb to the parse state.
3303-
*
3304-
* If the parse state container is an object, the jsonb is pushed as
3305-
* a value, not a key.
3306-
*
3307-
* This needs to be done using an iterator because pushJsonbValue doesn't
3308-
* like getting jbvBinary values, so we can't just push jb as a whole.
3309-
*/
3310-
static void
3311-
addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
3312-
{
3313-
JsonbIterator *it;
3314-
JsonbValue *o = &(*jbps)->contVal;
3315-
JsonbValue v;
3316-
JsonbIteratorToken type;
3317-
3318-
it = JsonbIteratorInit(&jb->root);
3319-
3320-
Assert(o->type == jbvArray || o->type == jbvObject);
3321-
3322-
if (JB_ROOT_IS_SCALAR(jb))
3323-
{
3324-
(void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3325-
(void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3326-
3327-
switch (o->type)
3328-
{
3329-
case jbvArray:
3330-
(void) pushJsonbValue(jbps, WJB_ELEM, &v);
3331-
break;
3332-
case jbvObject:
3333-
(void) pushJsonbValue(jbps, WJB_VALUE, &v);
3334-
break;
3335-
default:
3336-
elog(ERROR, "unexpected parent of nested structure");
3337-
}
3338-
}
3339-
else
3340-
{
3341-
while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3342-
{
3343-
if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3344-
(void) pushJsonbValue(jbps, type, &v);
3345-
else
3346-
(void) pushJsonbValue(jbps, type, NULL);
3347-
}
3348-
}
3349-
3350-
}
3351-
33523291
/*
33533292
* SQL function jsonb_pretty (jsonb)
33543293
*
@@ -3535,7 +3474,9 @@ jsonb_set(PG_FUNCTION_ARGS)
35353474
{
35363475
Jsonb *in = PG_GETARG_JSONB(0);
35373476
ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3538-
Jsonb *newval = PG_GETARG_JSONB(2);
3477+
Jsonb *newjsonb = PG_GETARG_JSONB(2);
3478+
JsonbValue newvalbuf;
3479+
JsonbValue *newval = JsonbToJsonbValue(newjsonb, &newvalbuf);
35393480
bool create = PG_GETARG_BOOL(3);
35403481
JsonbValue *res = NULL;
35413482
Datum *path_elems;
@@ -3566,7 +3507,7 @@ jsonb_set(PG_FUNCTION_ARGS)
35663507
it = JsonbIteratorInit(&in->root);
35673508

35683509
res = setPath(&it, path_elems, path_nulls, path_len, &st,
3569-
0, newval, false, create ? JB_PATH_CREATE : JB_PATH_NOOP);
3510+
0, newval, create ? JB_PATH_CREATE : JB_PATH_NOOP);
35703511

35713512
Assert(res != NULL);
35723513

@@ -3611,7 +3552,7 @@ jsonb_delete_path(PG_FUNCTION_ARGS)
36113552
it = JsonbIteratorInit(&in->root);
36123553

36133554
res = setPath(&it, path_elems, path_nulls, path_len, &st,
3614-
0, NULL, false, JB_PATH_DELETE);
3555+
0, NULL, JB_PATH_DELETE);
36153556

36163557
Assert(res != NULL);
36173558

@@ -3627,7 +3568,9 @@ jsonb_insert(PG_FUNCTION_ARGS)
36273568
{
36283569
Jsonb *in = PG_GETARG_JSONB(0);
36293570
ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3630-
Jsonb *newval = PG_GETARG_JSONB(2);
3571+
Jsonb *newjsonb = PG_GETARG_JSONB(2);
3572+
JsonbValue newvalbuf;
3573+
JsonbValue *newval = JsonbToJsonbValue(newjsonb, &newvalbuf);
36313574
bool after = PG_GETARG_BOOL(3);
36323575
JsonbValue *res = NULL;
36333576
Datum *path_elems;
@@ -3655,7 +3598,7 @@ jsonb_insert(PG_FUNCTION_ARGS)
36553598
it = JsonbIteratorInit(&in->root);
36563599

36573600
res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
3658-
false, after ? JB_PATH_INSERT_AFTER : JB_PATH_INSERT_BEFORE);
3601+
after ? JB_PATH_INSERT_AFTER : JB_PATH_INSERT_BEFORE);
36593602

36603603
Assert(res != NULL);
36613604

@@ -3790,7 +3733,7 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
37903733
JsonbValue *
37913734
setPath(JsonbIterator **it, Datum *path_elems,
37923735
bool *path_nulls, int path_len,
3793-
JsonbParseState **st, int level, Jsonb *newval, bool unpacked, int op_type)
3736+
JsonbParseState **st, int level, JsonbValue *newval, int op_type)
37943737
{
37953738
JsonbValue v;
37963739
JsonbIteratorToken r;
@@ -3811,15 +3754,15 @@ setPath(JsonbIterator **it, Datum *path_elems,
38113754
case WJB_BEGIN_ARRAY:
38123755
(void) pushJsonbValue(st, r, NULL);
38133756
setPathArray(it, path_elems, path_nulls, path_len, st, level,
3814-
newval, unpacked, v.val.array.nElems, op_type);
3757+
newval, v.val.array.nElems, op_type);
38153758
r = JsonbIteratorNext(it, &v, false);
38163759
Assert(r == WJB_END_ARRAY);
38173760
res = pushJsonbValue(st, r, NULL);
38183761
break;
38193762
case WJB_BEGIN_OBJECT:
38203763
(void) pushJsonbValue(st, r, NULL);
38213764
setPathObject(it, path_elems, path_nulls, path_len, st, level,
3822-
newval, unpacked, v.val.object.nPairs, op_type);
3765+
newval, v.val.object.nPairs, op_type);
38233766
r = JsonbIteratorNext(it, &v, true);
38243767
Assert(r == WJB_END_OBJECT);
38253768
res = pushJsonbValue(st, r, NULL);
@@ -3843,10 +3786,11 @@ setPath(JsonbIterator **it, Datum *path_elems,
38433786
static void
38443787
setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
38453788
int path_len, JsonbParseState **st, int level,
3846-
Jsonb *newval, bool unpacked, uint32 npairs, int op_type)
3789+
JsonbValue *newval, uint32 npairs, int op_type)
38473790
{
38483791
int i;
3849-
JsonbValue k, v;
3792+
JsonbValue k,
3793+
v;
38503794
bool done = false;
38513795

38523796
if (level >= path_len || path_nulls[level])
@@ -3863,7 +3807,7 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
38633807
newkey.val.string.val = VARDATA_ANY(path_elems[level]);
38643808

38653809
(void) pushJsonbValue(st, WJB_KEY, &newkey);
3866-
add_newval(st, newval, unpacked);
3810+
(void) pushJsonbValue(st, WJB_VALUE, newval);
38673811
}
38683812

38693813
for (i = 0; i < npairs; i++)
@@ -3894,15 +3838,15 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
38943838
if (!(op_type & JB_PATH_DELETE))
38953839
{
38963840
(void) pushJsonbValue(st, WJB_KEY, &k);
3897-
add_newval(st, newval, unpacked);
3841+
(void) pushJsonbValue(st, WJB_VALUE, newval);
38983842
}
38993843
done = true;
39003844
}
39013845
else
39023846
{
39033847
(void) pushJsonbValue(st, r, &k);
39043848
setPath(it, path_elems, path_nulls, path_len,
3905-
st, level + 1, newval, unpacked, op_type);
3849+
st, level + 1, newval, op_type);
39063850
}
39073851
}
39083852
else
@@ -3917,7 +3861,7 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
39173861
newkey.val.string.val = VARDATA_ANY(path_elems[level]);
39183862

39193863
(void) pushJsonbValue(st, WJB_KEY, &newkey);
3920-
add_newval(st, newval, unpacked);
3864+
(void) pushJsonbValue(st, WJB_VALUE, newval);
39213865
}
39223866

39233867
(void) pushJsonbValue(st, r, &k);
@@ -3949,7 +3893,7 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
39493893
static void
39503894
setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
39513895
int path_len, JsonbParseState **st, int level,
3952-
Jsonb *newval, bool unpacked, uint32 nelems, int op_type)
3896+
Jsonb *newval, uint32 nelems, int op_type)
39533897
{
39543898
JsonbValue v;
39553899
int idx,
@@ -3997,7 +3941,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
39973941
(op_type & JB_PATH_CREATE_OR_INSERT))
39983942
{
39993943
Assert(newval != NULL);
4000-
add_newval(st, newval, unpacked);
3944+
(void) pushJsonbValue(st, WJB_ELEM, newval);
40013945
done = true;
40023946
}
40033947

@@ -4013,7 +3957,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
40133957
r = JsonbIteratorNext(it, &v, true); /* skip */
40143958

40153959
if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
4016-
add_newval(st, newval, unpacked);
3960+
(void) pushJsonbValue(st, WJB_ELEM, newval);
40173961

40183962
/*
40193963
* We should keep current value only in case of
@@ -4024,13 +3968,13 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
40243968
(void) pushJsonbValue(st, r, &v);
40253969

40263970
if (op_type & JB_PATH_INSERT_AFTER)
4027-
add_newval(st, newval, unpacked);
3971+
(void) pushJsonbValue(st, WJB_ELEM, newval);
40283972

40293973
done = true;
40303974
}
40313975
else
40323976
(void) setPath(it, path_elems, path_nulls, path_len,
4033-
st, level + 1, newval, unpacked, op_type);
3977+
st, level + 1, newval, op_type);
40343978
}
40353979
else
40363980
{
@@ -4058,7 +4002,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
40584002
if (op_type & JB_PATH_CREATE_OR_INSERT && !done &&
40594003
level == path_len - 1 && i == nelems - 1)
40604004
{
4061-
add_newval(st, newval, unpacked);
4005+
(void) pushJsonbValue(st, WJB_ELEM, newval);
40624006
}
40634007
}
40644008
}
@@ -4234,7 +4178,7 @@ jsonb_set_element(Datum jsonbdatum, text **path, int path_len,
42344178
path_nulls[i] = false;
42354179

42364180
res = setPath(&it, (Datum *) path, path_nulls, path_len, &state, 0,
4237-
(void *) newval, true, JB_PATH_CREATE);
4181+
newval, JB_PATH_CREATE);
42384182

42394183
PG_RETURN_JSONB(JsonbValueToJsonb(res));
42404184
}

src/include/utils/jsonb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
426426
extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container);
427427
extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,
428428
bool skipNested);
429+
extern JsonbValue *JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val);
429430
extern Jsonb *JsonbValueToJsonb(JsonbValue *val);
430431
extern bool JsonbDeepContains(JsonbIterator **val,
431432
JsonbIterator **mContained);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy