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
148142static Datum jsonb_get_element (Datum datum , text * * path , int path_len , bool * isNull );
149143static 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 );
153146static 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 );
157149static 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 );
162152static Datum jsonb_subscription_evaluate (PG_FUNCTION_ARGS );
163153static 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,
37903733JsonbValue *
37913734setPath (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,
38433786static void
38443787setPathObject (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,
39493893static void
39503894setPathArray (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}
0 commit comments