@@ -3628,36 +3628,39 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
3628
3628
rk1 ,
3629
3629
rk2 ;
3630
3630
3631
- r1 = rk1 = JsonbIteratorNext (it1 , & v1 , false);
3632
- r2 = rk2 = JsonbIteratorNext (it2 , & v2 , false);
3631
+ rk1 = JsonbIteratorNext (it1 , & v1 , false);
3632
+ rk2 = JsonbIteratorNext (it2 , & v2 , false);
3633
3633
3634
3634
/*
3635
- * Both elements are objects.
3635
+ * JsonbIteratorNext reports raw scalars as if they were single-element
3636
+ * arrays; hence we only need consider "object" and "array" cases here.
3636
3637
*/
3637
3638
if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT )
3638
3639
{
3639
3640
/*
3640
- * Append the all tokens from v1 to res, except last WJB_END_OBJECT
3641
+ * Both inputs are objects.
3642
+ *
3643
+ * Append all the tokens from v1 to res, except last WJB_END_OBJECT
3641
3644
* (because res will not be finished yet).
3642
3645
*/
3643
- pushJsonbValue (state , r1 , NULL );
3646
+ pushJsonbValue (state , rk1 , NULL );
3644
3647
while ((r1 = JsonbIteratorNext (it1 , & v1 , true)) != WJB_END_OBJECT )
3645
3648
pushJsonbValue (state , r1 , & v1 );
3646
3649
3647
3650
/*
3648
- * Append the all tokens from v2 to res, include last WJB_END_OBJECT
3649
- * (the concatenation will be completed).
3651
+ * Append all the tokens from v2 to res, including last WJB_END_OBJECT
3652
+ * (the concatenation will be completed). Any duplicate keys will
3653
+ * automatically override the value from the first object.
3650
3654
*/
3651
- while ((r2 = JsonbIteratorNext (it2 , & v2 , true)) != 0 )
3655
+ while ((r2 = JsonbIteratorNext (it2 , & v2 , true)) != WJB_DONE )
3652
3656
res = pushJsonbValue (state , r2 , r2 != WJB_END_OBJECT ? & v2 : NULL );
3653
3657
}
3654
-
3655
- /*
3656
- * Both elements are arrays (either can be scalar).
3657
- */
3658
3658
else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY )
3659
3659
{
3660
- pushJsonbValue (state , r1 , NULL );
3660
+ /*
3661
+ * Both inputs are arrays.
3662
+ */
3663
+ pushJsonbValue (state , rk1 , NULL );
3661
3664
3662
3665
while ((r1 = JsonbIteratorNext (it1 , & v1 , true)) != WJB_END_ARRAY )
3663
3666
{
@@ -3673,48 +3676,40 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
3673
3676
3674
3677
res = pushJsonbValue (state , WJB_END_ARRAY , NULL /* signal to sort */ );
3675
3678
}
3676
- /* have we got array || object or object || array? */
3677
- else if (((rk1 == WJB_BEGIN_ARRAY && !(* it1 )-> isScalar ) && rk2 == WJB_BEGIN_OBJECT ) ||
3678
- (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(* it2 )-> isScalar )))
3679
+ else if (rk1 == WJB_BEGIN_OBJECT )
3679
3680
{
3680
-
3681
- JsonbIterator * * it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2 ;
3682
- JsonbIterator * * it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2 ;
3683
-
3684
- bool prepend = (rk1 == WJB_BEGIN_OBJECT );
3681
+ /*
3682
+ * We have object || array.
3683
+ */
3684
+ Assert (rk2 == WJB_BEGIN_ARRAY );
3685
3685
3686
3686
pushJsonbValue (state , WJB_BEGIN_ARRAY , NULL );
3687
3687
3688
- if (prepend )
3689
- {
3690
- pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
3691
- while ((r1 = JsonbIteratorNext (it_object , & v1 , true)) != 0 )
3692
- pushJsonbValue (state , r1 , r1 != WJB_END_OBJECT ? & v1 : NULL );
3688
+ pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
3689
+ while ((r1 = JsonbIteratorNext (it1 , & v1 , true)) != WJB_DONE )
3690
+ pushJsonbValue (state , r1 , r1 != WJB_END_OBJECT ? & v1 : NULL );
3693
3691
3694
- while ((r2 = JsonbIteratorNext (it_array , & v2 , true)) != 0 )
3695
- res = pushJsonbValue (state , r2 , r2 != WJB_END_ARRAY ? & v2 : NULL );
3696
- }
3697
- else
3698
- {
3699
- while ((r1 = JsonbIteratorNext (it_array , & v1 , true)) != WJB_END_ARRAY )
3700
- pushJsonbValue (state , r1 , & v1 );
3701
-
3702
- pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
3703
- while ((r2 = JsonbIteratorNext (it_object , & v2 , true)) != 0 )
3704
- pushJsonbValue (state , r2 , r2 != WJB_END_OBJECT ? & v2 : NULL );
3705
-
3706
- res = pushJsonbValue (state , WJB_END_ARRAY , NULL );
3707
- }
3692
+ while ((r2 = JsonbIteratorNext (it2 , & v2 , true)) != WJB_DONE )
3693
+ res = pushJsonbValue (state , r2 , r2 != WJB_END_ARRAY ? & v2 : NULL );
3708
3694
}
3709
3695
else
3710
3696
{
3711
3697
/*
3712
- * This must be scalar || object or object || scalar, as that's all
3713
- * that's left. Both of these make no sense, so error out.
3698
+ * We have array || object.
3714
3699
*/
3715
- ereport (ERROR ,
3716
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
3717
- errmsg ("invalid concatenation of jsonb objects" )));
3700
+ Assert (rk1 == WJB_BEGIN_ARRAY );
3701
+ Assert (rk2 == WJB_BEGIN_OBJECT );
3702
+
3703
+ pushJsonbValue (state , WJB_BEGIN_ARRAY , NULL );
3704
+
3705
+ while ((r1 = JsonbIteratorNext (it1 , & v1 , true)) != WJB_END_ARRAY )
3706
+ pushJsonbValue (state , r1 , & v1 );
3707
+
3708
+ pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
3709
+ while ((r2 = JsonbIteratorNext (it2 , & v2 , true)) != WJB_DONE )
3710
+ pushJsonbValue (state , r2 , r2 != WJB_END_OBJECT ? & v2 : NULL );
3711
+
3712
+ res = pushJsonbValue (state , WJB_END_ARRAY , NULL );
3718
3713
}
3719
3714
3720
3715
return res ;
0 commit comments