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)