@@ -4690,11 +4690,14 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
4690
4690
rk2 = JsonbIteratorNext (it2 , & v2 , false);
4691
4691
4692
4692
/*
4693
- * Both elements are objects.
4693
+ * JsonbIteratorNext reports raw scalars as if they were single-element
4694
+ * arrays; hence we only need consider "object" and "array" cases here.
4694
4695
*/
4695
4696
if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT )
4696
4697
{
4697
4698
/*
4699
+ * Both inputs are objects.
4700
+ *
4698
4701
* Append all the tokens from v1 to res, except last WJB_END_OBJECT
4699
4702
* (because res will not be finished yet).
4700
4703
*/
@@ -4703,18 +4706,18 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
4703
4706
pushJsonbValue (state , r1 , & v1 );
4704
4707
4705
4708
/*
4706
- * Append all the tokens from v2 to res, include last WJB_END_OBJECT
4707
- * (the concatenation will be completed).
4709
+ * Append all the tokens from v2 to res, including last WJB_END_OBJECT
4710
+ * (the concatenation will be completed). Any duplicate keys will
4711
+ * automatically override the value from the first object.
4708
4712
*/
4709
4713
while ((r2 = JsonbIteratorNext (it2 , & v2 , true)) != WJB_DONE )
4710
4714
res = pushJsonbValue (state , r2 , r2 != WJB_END_OBJECT ? & v2 : NULL );
4711
4715
}
4712
-
4713
- /*
4714
- * Both elements are arrays (either can be scalar).
4715
- */
4716
4716
else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY )
4717
4717
{
4718
+ /*
4719
+ * Both inputs are arrays.
4720
+ */
4718
4721
pushJsonbValue (state , rk1 , NULL );
4719
4722
4720
4723
while ((r1 = JsonbIteratorNext (it1 , & v1 , true)) != WJB_END_ARRAY )
@@ -4731,46 +4734,40 @@ IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
4731
4734
4732
4735
res = pushJsonbValue (state , WJB_END_ARRAY , NULL /* signal to sort */ );
4733
4736
}
4734
- /* have we got array || object or object || array? */
4735
- else if (((rk1 == WJB_BEGIN_ARRAY && !(* it1 )-> isScalar ) && rk2 == WJB_BEGIN_OBJECT ) ||
4736
- (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(* it2 )-> isScalar )))
4737
+ else if (rk1 == WJB_BEGIN_OBJECT )
4737
4738
{
4738
- JsonbIterator * * it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2 ;
4739
- JsonbIterator * * it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2 ;
4740
- bool prepend = (rk1 == WJB_BEGIN_OBJECT );
4739
+ /*
4740
+ * We have object || array.
4741
+ */
4742
+ Assert (rk2 == WJB_BEGIN_ARRAY );
4741
4743
4742
4744
pushJsonbValue (state , WJB_BEGIN_ARRAY , NULL );
4743
4745
4744
- if (prepend )
4745
- {
4746
- pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
4747
- while ((r1 = JsonbIteratorNext (it_object , & v1 , true)) != WJB_DONE )
4748
- pushJsonbValue (state , r1 , r1 != WJB_END_OBJECT ? & v1 : NULL );
4749
-
4750
- while ((r2 = JsonbIteratorNext (it_array , & v2 , true)) != WJB_DONE )
4751
- res = pushJsonbValue (state , r2 , r2 != WJB_END_ARRAY ? & v2 : NULL );
4752
- }
4753
- else
4754
- {
4755
- while ((r1 = JsonbIteratorNext (it_array , & v1 , true)) != WJB_END_ARRAY )
4756
- pushJsonbValue (state , r1 , & v1 );
4757
-
4758
- pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
4759
- while ((r2 = JsonbIteratorNext (it_object , & v2 , true)) != WJB_DONE )
4760
- pushJsonbValue (state , r2 , r2 != WJB_END_OBJECT ? & v2 : NULL );
4746
+ pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
4747
+ while ((r1 = JsonbIteratorNext (it1 , & v1 , true)) != WJB_DONE )
4748
+ pushJsonbValue (state , r1 , r1 != WJB_END_OBJECT ? & v1 : NULL );
4761
4749
4762
- res = pushJsonbValue ( state , WJB_END_ARRAY , NULL );
4763
- }
4750
+ while (( r2 = JsonbIteratorNext ( it2 , & v2 , true)) != WJB_DONE )
4751
+ res = pushJsonbValue ( state , r2 , r2 != WJB_END_ARRAY ? & v2 : NULL );
4764
4752
}
4765
4753
else
4766
4754
{
4767
4755
/*
4768
- * This must be scalar || object or object || scalar, as that's all
4769
- * that's left. Both of these make no sense, so error out.
4756
+ * We have array || object.
4770
4757
*/
4771
- ereport (ERROR ,
4772
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
4773
- errmsg ("invalid concatenation of jsonb objects" )));
4758
+ Assert (rk1 == WJB_BEGIN_ARRAY );
4759
+ Assert (rk2 == WJB_BEGIN_OBJECT );
4760
+
4761
+ pushJsonbValue (state , WJB_BEGIN_ARRAY , NULL );
4762
+
4763
+ while ((r1 = JsonbIteratorNext (it1 , & v1 , true)) != WJB_END_ARRAY )
4764
+ pushJsonbValue (state , r1 , & v1 );
4765
+
4766
+ pushJsonbValue (state , WJB_BEGIN_OBJECT , NULL );
4767
+ while ((r2 = JsonbIteratorNext (it2 , & v2 , true)) != WJB_DONE )
4768
+ pushJsonbValue (state , r2 , r2 != WJB_END_OBJECT ? & v2 : NULL );
4769
+
4770
+ res = pushJsonbValue (state , WJB_END_ARRAY , NULL );
4774
4771
}
4775
4772
4776
4773
return res ;
0 commit comments