Commit e7e3ac2d authored by Andrew Dunstan's avatar Andrew Dunstan

Fix the fastpath rule for jsonb_concat with an empty operand.

To prevent perverse results, we now only return the other operand if
it's not scalar, and if both operands are of the same kind (array or
object).

Original bug complaint and patch from Oskari Saarenmaa, extended by me
to cover the cases of different kinds of jsonb.

Backpatch to 9.5 where jsonb_concat was introduced.
parent c193b8ca
......@@ -3359,12 +3359,18 @@ jsonb_concat(PG_FUNCTION_ARGS)
*it2;
/*
* If one of the jsonb is empty, just return other.
* If one of the jsonb is empty, just return the other if it's not
* scalar and both are of the same kind. If it's a scalar or they are
* of different kinds we need to perform the concatenation even if one is
* empty.
*/
if (JB_ROOT_COUNT(jb1) == 0)
PG_RETURN_JSONB(jb2);
else if (JB_ROOT_COUNT(jb2) == 0)
PG_RETURN_JSONB(jb1);
if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
{
if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
PG_RETURN_JSONB(jb2);
else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
PG_RETURN_JSONB(jb1);
}
it1 = JsonbIteratorInit(&jb1->root);
it2 = JsonbIteratorInit(&jb2->root);
......
......@@ -2912,6 +2912,42 @@ select '"c"' || '["a", "b"]'::jsonb;
["c", "a", "b"]
(1 row)
select '[]'::jsonb || '["a"]'::jsonb;
?column?
----------
["a"]
(1 row)
select '[]'::jsonb || '"a"'::jsonb;
?column?
----------
["a"]
(1 row)
select '"b"'::jsonb || '"a"'::jsonb;
?column?
------------
["b", "a"]
(1 row)
select '{}'::jsonb || '{"a":"b"}'::jsonb;
?column?
------------
{"a": "b"}
(1 row)
select '[]'::jsonb || '{"a":"b"}'::jsonb;
?column?
--------------
[{"a": "b"}]
(1 row)
select '{"a":"b"}'::jsonb || '[]'::jsonb;
?column?
--------------
[{"a": "b"}]
(1 row)
select '"a"'::jsonb || '{"a":1}';
ERROR: invalid concatenation of jsonb objects
select '{"a":1}' || '"a"'::jsonb;
......
......@@ -2912,6 +2912,42 @@ select '"c"' || '["a", "b"]'::jsonb;
["c", "a", "b"]
(1 row)
select '[]'::jsonb || '["a"]'::jsonb;
?column?
----------
["a"]
(1 row)
select '[]'::jsonb || '"a"'::jsonb;
?column?
----------
["a"]
(1 row)
select '"b"'::jsonb || '"a"'::jsonb;
?column?
------------
["b", "a"]
(1 row)
select '{}'::jsonb || '{"a":"b"}'::jsonb;
?column?
------------
{"a": "b"}
(1 row)
select '[]'::jsonb || '{"a":"b"}'::jsonb;
?column?
--------------
[{"a": "b"}]
(1 row)
select '{"a":"b"}'::jsonb || '[]'::jsonb;
?column?
--------------
[{"a": "b"}]
(1 row)
select '"a"'::jsonb || '{"a":1}';
ERROR: invalid concatenation of jsonb objects
select '{"a":1}' || '"a"'::jsonb;
......
......@@ -718,6 +718,13 @@ select '["c"]' || '["a", "b"]'::jsonb;
select '["a", "b"]'::jsonb || '"c"';
select '"c"' || '["a", "b"]'::jsonb;
select '[]'::jsonb || '["a"]'::jsonb;
select '[]'::jsonb || '"a"'::jsonb;
select '"b"'::jsonb || '"a"'::jsonb;
select '{}'::jsonb || '{"a":"b"}'::jsonb;
select '[]'::jsonb || '{"a":"b"}'::jsonb;
select '{"a":"b"}'::jsonb || '[]'::jsonb;
select '"a"'::jsonb || '{"a":1}';
select '{"a":1}' || '"a"'::jsonb;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment