From 6513017eabbd4bdd4980056ed73ca8e3fbe58d1b Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Fri, 5 Jun 2015 13:55:48 -0700 Subject: [PATCH] Desupport jsonb subscript deletion on objects Supporting deletion of JSON pairs within jsonb objects using an array-style integer subscript allowed for surprising outcomes. This was mostly due to the implementation-defined ordering of pairs within objects for jsonb. It also seems desirable to make jsonb integer subscript deletion consistent with the 9.4 era general purpose integer subscripting operator for jsonb (although that operator returns NULL when an object is encountered, while we prefer to throw an error). --- doc/src/sgml/func.sgml | 5 ++-- src/backend/utils/adt/jsonfuncs.c | 5 ++++ src/test/regress/expected/jsonb.out | 56 ++--------------------------------- src/test/regress/expected/jsonb_1.out | 56 ++--------------------------------- src/test/regress/sql/jsonb.sql | 11 +------ 5 files changed, 13 insertions(+), 120 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index c6e3540..be0c3d6 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -10309,8 +10309,9 @@ table2-mapping - integer - Delete the field or element with specified index (Negative - integers count from the end) + Delete the array element with specified index (Negative + integers count from the end). Throws an error if top level + container is not an array. '["a", "b"]'::jsonb - 1 diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index f87ba77..c14d3f7 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -3400,6 +3400,11 @@ jsonb_delete_idx(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot delete from scalar"))); + if (JB_ROOT_IS_OBJECT(in)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot delete from object using integer subscript"))); + if (JB_ROOT_COUNT(in) == 0) PG_RETURN_JSONB(in); diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 412bf97..e6654d4 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -3031,54 +3031,6 @@ select '["a","b","c"]'::jsonb - -4; ["a", "b", "c"] (1 row) -select '{"a":1, "b":2, "c":3}'::jsonb - 3; - ?column? --------------------------- - {"a": 1, "b": 2, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - 2; - ?column? ------------------- - {"a": 1, "b": 2} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - 1; - ?column? ------------------- - {"a": 1, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - 0; - ?column? ------------------- - {"b": 2, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -1; - ?column? ------------------- - {"a": 1, "b": 2} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -2; - ?column? ------------------- - {"a": 1, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -3; - ?column? ------------------- - {"b": 2, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -4; - ?column? --------------------------- - {"a": 1, "b": 2, "c": 3} -(1 row) - select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '[1,2,3]'); jsonb_set -------------------------------------------------------------------------- @@ -3192,12 +3144,8 @@ select '[]'::jsonb - 'a'; select '"a"'::jsonb - 1; -- error ERROR: cannot delete from scalar -select '{}'::jsonb - 1 ; - ?column? ----------- - {} -(1 row) - +select '{}'::jsonb - 1; -- error +ERROR: cannot delete from object using integer subscript select '[]'::jsonb - 1; ?column? ---------- diff --git a/src/test/regress/expected/jsonb_1.out b/src/test/regress/expected/jsonb_1.out index 4ead74b..0a1ec93 100644 --- a/src/test/regress/expected/jsonb_1.out +++ b/src/test/regress/expected/jsonb_1.out @@ -3031,54 +3031,6 @@ select '["a","b","c"]'::jsonb - -4; ["a", "b", "c"] (1 row) -select '{"a":1, "b":2, "c":3}'::jsonb - 3; - ?column? --------------------------- - {"a": 1, "b": 2, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - 2; - ?column? ------------------- - {"a": 1, "b": 2} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - 1; - ?column? ------------------- - {"a": 1, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - 0; - ?column? ------------------- - {"b": 2, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -1; - ?column? ------------------- - {"a": 1, "b": 2} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -2; - ?column? ------------------- - {"a": 1, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -3; - ?column? ------------------- - {"b": 2, "c": 3} -(1 row) - -select '{"a":1, "b":2, "c":3}'::jsonb - -4; - ?column? --------------------------- - {"a": 1, "b": 2, "c": 3} -(1 row) - select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '[1,2,3]'); jsonb_set -------------------------------------------------------------------------- @@ -3192,12 +3144,8 @@ select '[]'::jsonb - 'a'; select '"a"'::jsonb - 1; -- error ERROR: cannot delete from scalar -select '{}'::jsonb - 1 ; - ?column? ----------- - {} -(1 row) - +select '{}'::jsonb - 1; -- error +ERROR: cannot delete from object using integer subscript select '[]'::jsonb - 1; ?column? ---------- diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 2abec22..29c82a2 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -738,15 +738,6 @@ select '["a","b","c"]'::jsonb - -2; select '["a","b","c"]'::jsonb - -3; select '["a","b","c"]'::jsonb - -4; -select '{"a":1, "b":2, "c":3}'::jsonb - 3; -select '{"a":1, "b":2, "c":3}'::jsonb - 2; -select '{"a":1, "b":2, "c":3}'::jsonb - 1; -select '{"a":1, "b":2, "c":3}'::jsonb - 0; -select '{"a":1, "b":2, "c":3}'::jsonb - -1; -select '{"a":1, "b":2, "c":3}'::jsonb - -2; -select '{"a":1, "b":2, "c":3}'::jsonb - -3; -select '{"a":1, "b":2, "c":3}'::jsonb - -4; - select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '[1,2,3]'); select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '[1,2,3]'); select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,1,0}', '[1,2,3]'); @@ -775,7 +766,7 @@ select '"a"'::jsonb - 'a'; -- error select '{}'::jsonb - 'a'; select '[]'::jsonb - 'a'; select '"a"'::jsonb - 1; -- error -select '{}'::jsonb - 1 ; +select '{}'::jsonb - 1; -- error select '[]'::jsonb - 1; select '"a"'::jsonb - '{a}'::text[]; -- error select '{}'::jsonb - '{a}'::text[]; -- 1.9.1