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