Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6739aa2

Browse files
committed
Clean up and simplify jsonb_concat code.
Some of this is made possible by commit 9b74f32 which lets pushJsonbValue handle binary Jsonb values, meaning that clients no longer have to, and some is just doing things in simpler and more straightforward ways.
1 parent 8339e70 commit 6739aa2

File tree

1 file changed

+27
-97
lines changed

1 file changed

+27
-97
lines changed

src/backend/utils/adt/jsonfuncs.c

+27-97
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
127127
/* functions supporting jsonb_delete, jsonb_replace and jsonb_concat */
128128
static JsonbValue *IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
129129
JsonbParseState **state);
130-
static JsonbValue *walkJsonb(JsonbIterator **it, JsonbParseState **state, bool stop_at_level_zero);
131130
static JsonbValue *replacePath(JsonbIterator **it, Datum *path_elems,
132131
bool *path_nulls, int path_len,
133132
JsonbParseState **st, int level, Jsonb *newval);
@@ -3287,7 +3286,6 @@ jsonb_pretty(PG_FUNCTION_ARGS)
32873286
PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
32883287
}
32893288

3290-
32913289
/*
32923290
* SQL function jsonb_concat (jsonb, jsonb)
32933291
*
@@ -3298,7 +3296,6 @@ jsonb_concat(PG_FUNCTION_ARGS)
32983296
{
32993297
Jsonb *jb1 = PG_GETARG_JSONB(0);
33003298
Jsonb *jb2 = PG_GETARG_JSONB(1);
3301-
Jsonb *out = palloc(VARSIZE(jb1) + VARSIZE(jb2));
33023299
JsonbParseState *state = NULL;
33033300
JsonbValue *res;
33043301
JsonbIterator *it1,
@@ -3308,35 +3305,18 @@ jsonb_concat(PG_FUNCTION_ARGS)
33083305
* If one of the jsonb is empty, just return other.
33093306
*/
33103307
if (JB_ROOT_COUNT(jb1) == 0)
3311-
{
3312-
memcpy(out, jb2, VARSIZE(jb2));
3313-
PG_RETURN_POINTER(out);
3314-
}
3308+
PG_RETURN_JSONB(jb2);
33153309
else if (JB_ROOT_COUNT(jb2) == 0)
3316-
{
3317-
memcpy(out, jb1, VARSIZE(jb1));
3318-
PG_RETURN_POINTER(out);
3319-
}
3310+
PG_RETURN_JSONB(jb1);
33203311

33213312
it1 = JsonbIteratorInit(&jb1->root);
33223313
it2 = JsonbIteratorInit(&jb2->root);
33233314

33243315
res = IteratorConcat(&it1, &it2, &state);
33253316

3326-
if (res == NULL || (res->type == jbvArray && res->val.array.nElems == 0) ||
3327-
(res->type == jbvObject && res->val.object.nPairs == 0))
3328-
{
3329-
SET_VARSIZE(out, VARHDRSZ);
3330-
}
3331-
else
3332-
{
3333-
if (res->type == jbvArray && res->val.array.nElems > 1)
3334-
res->val.array.rawScalar = false;
3335-
3336-
out = JsonbValueToJsonb(res);
3337-
}
3317+
Assert(res != NULL);
33383318

3339-
PG_RETURN_JSONB(out);
3319+
PG_RETURN_JSONB(JsonbValueToJsonb(res));
33403320
}
33413321

33423322

@@ -3550,7 +3530,6 @@ jsonb_delete_path(PG_FUNCTION_ARGS)
35503530
PG_RETURN_JSONB(JsonbValueToJsonb(res));
35513531
}
35523532

3553-
35543533
/*
35553534
* Iterate over all jsonb objects and merge them into one.
35563535
* The logic of this function copied from the same hstore function,
@@ -3578,67 +3557,42 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
35783557
*/
35793558
if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
35803559
{
3581-
int level = 1;
3582-
35833560
/*
35843561
* Append the all tokens from v1 to res, except last WJB_END_OBJECT
35853562
* (because res will not be finished yet).
35863563
*/
3587-
(void) pushJsonbValue(state, r1, NULL);
3588-
while ((r1 = JsonbIteratorNext(it1, &v1, false)) != 0)
3589-
{
3590-
if (r1 == WJB_BEGIN_OBJECT)
3591-
++level;
3592-
else if (r1 == WJB_END_OBJECT)
3593-
--level;
3594-
3595-
if (level != 0)
3596-
res = pushJsonbValue(state, r1, r1 < WJB_BEGIN_ARRAY ? &v1 : NULL);
3597-
}
3564+
pushJsonbValue(state, r1, NULL);
3565+
while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
3566+
pushJsonbValue(state, r1, &v1 );
35983567

35993568
/*
36003569
* Append the all tokens from v2 to res, include last WJB_END_OBJECT
36013570
* (the concatenation will be completed).
36023571
*/
3603-
while ((r2 = JsonbIteratorNext(it2, &v2, false)) != 0)
3604-
res = pushJsonbValue(state, r2, r2 < WJB_BEGIN_ARRAY ? &v2 : NULL);
3572+
while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3573+
res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
36053574
}
36063575

36073576
/*
36083577
* Both elements are arrays (either can be scalar).
36093578
*/
36103579
else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
36113580
{
3612-
res = pushJsonbValue(state, r1, NULL);
3613-
for (;;)
3614-
{
3615-
r1 = JsonbIteratorNext(it1, &v1, true);
3616-
if (r1 == WJB_END_OBJECT || r1 == WJB_END_ARRAY)
3617-
break;
3581+
pushJsonbValue(state, r1, NULL);
36183582

3619-
Assert(r1 == WJB_KEY || r1 == WJB_VALUE || r1 == WJB_ELEM);
3583+
while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
3584+
{
3585+
Assert(r1 == WJB_ELEM);
36203586
pushJsonbValue(state, r1, &v1);
36213587
}
36223588

3623-
while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3589+
while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
36243590
{
3625-
if (!(r2 == WJB_END_OBJECT || r2 == WJB_END_ARRAY))
3626-
{
3627-
if (rk1 == WJB_BEGIN_OBJECT)
3628-
{
3629-
pushJsonbValue(state, WJB_KEY, NULL);
3630-
r2 = JsonbIteratorNext(it2, &v2, true);
3631-
Assert(r2 == WJB_ELEM);
3632-
pushJsonbValue(state, WJB_VALUE, &v2);
3633-
}
3634-
else
3635-
pushJsonbValue(state, WJB_ELEM, &v2);
3636-
}
3591+
Assert(r2 == WJB_ELEM);
3592+
pushJsonbValue(state, WJB_ELEM, &v2);
36373593
}
36383594

3639-
res = pushJsonbValue(state,
3640-
(rk1 == WJB_BEGIN_OBJECT) ? WJB_END_OBJECT : WJB_END_ARRAY,
3641-
NULL /* signal to sort */ );
3595+
res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
36423596
}
36433597
/* have we got array || object or object || array? */
36443598
else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
@@ -3648,22 +3602,27 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
36483602
JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
36493603
JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
36503604

3651-
bool prepend = (rk1 == WJB_BEGIN_OBJECT) ? true : false;
3605+
bool prepend = (rk1 == WJB_BEGIN_OBJECT);
36523606

36533607
pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
3608+
36543609
if (prepend)
36553610
{
36563611
pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3657-
walkJsonb(it_object, state, false);
3612+
while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
3613+
pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
36583614

3659-
res = walkJsonb(it_array, state, false);
3615+
while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
3616+
res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
36603617
}
36613618
else
36623619
{
3663-
walkJsonb(it_array, state, true);
3620+
while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
3621+
pushJsonbValue(state, r1, &v1);
36643622

36653623
pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
3666-
walkJsonb(it_object, state, false);
3624+
while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
3625+
pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
36673626

36683627
res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
36693628
}
@@ -3682,35 +3641,6 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
36823641
return res;
36833642
}
36843643

3685-
/*
3686-
* copy elements from the iterator to the parse state
3687-
* stopping at level zero if required.
3688-
*/
3689-
static JsonbValue *
3690-
walkJsonb(JsonbIterator **it, JsonbParseState **state, bool stop_at_level_zero)
3691-
{
3692-
uint32 r,
3693-
level = 1;
3694-
JsonbValue v;
3695-
JsonbValue *res = NULL;
3696-
3697-
while ((r = JsonbIteratorNext(it, &v, false)) != WJB_DONE)
3698-
{
3699-
if (r == WJB_BEGIN_OBJECT || r == WJB_BEGIN_ARRAY)
3700-
++level;
3701-
else if (r == WJB_END_OBJECT || r == WJB_END_ARRAY)
3702-
--level;
3703-
3704-
if (stop_at_level_zero && level == 0)
3705-
break;
3706-
3707-
res = pushJsonbValue(state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3708-
}
3709-
3710-
return res;
3711-
}
3712-
3713-
37143644
/*
37153645
* do most of the heavy work for jsonb_replace
37163646
*/

0 commit comments

Comments
 (0)