From 94c745eb189e2122a3ff86c24443b11408ea2376 Mon Sep 17 00:00:00 2001 From: Andrew Dunstan Date: Sun, 21 Feb 2016 10:30:49 -0500 Subject: [PATCH] Fix two-argument jsonb_object when called with empty arrays Some over-eager copy-and-pasting on my part resulted in a nonsense result being returned in this case. I have adopted the same pattern for handling this case as is used in the one argument form of the function, i.e. we just skip over the code that adds values to the object. Diagnosis and patch from Michael Paquier, although not quite his solution. Fixes bug #13936. Backpatch to 9.5 where jsonb_object was introduced. --- src/backend/utils/adt/jsonb.c | 7 ++++--- src/test/regress/expected/json.out | 14 ++++++++++++++ src/test/regress/expected/jsonb.out | 14 ++++++++++++++ src/test/regress/sql/json.sql | 6 ++++++ src/test/regress/sql/jsonb.sql | 6 ++++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index 9151a13e3c..256ef80ece 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -1455,7 +1455,7 @@ jsonb_object_two_arg(PG_FUNCTION_ARGS) errmsg("wrong number of array subscripts"))); if (nkdims == 0) - PG_RETURN_DATUM(CStringGetTextDatum("{}")); + goto close_object; deconstruct_array(key_array, TEXTOID, -1, false, 'i', @@ -1509,13 +1509,14 @@ jsonb_object_two_arg(PG_FUNCTION_ARGS) (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v); } - result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL); - pfree(key_datums); pfree(key_nulls); pfree(val_datums); pfree(val_nulls); +close_object: + result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL); + PG_RETURN_POINTER(JsonbValueToJsonb(result.res)); } diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out index 0ced17e130..502f983889 100644 --- a/src/test/regress/expected/json.out +++ b/src/test/regress/expected/json.out @@ -1510,6 +1510,20 @@ INSERT INTO foo VALUES (999999, NULL, 'bar'); SELECT json_object_agg(name, type) FROM foo; ERROR: field name must not be null -- json_object +-- empty object, one dimension +SELECT json_object('{}'); + json_object +------------- + {} +(1 row) + +-- empty object, two dimensions +SELECT json_object('{}', '{}'); + json_object +------------- + {} +(1 row) + -- one dimension SELECT json_object('{a,1,b,2,3,NULL,"d e f","a b c"}'); json_object diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 72fe808734..4789e4e57b 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -1410,6 +1410,20 @@ INSERT INTO foo VALUES (999999, NULL, 'bar'); SELECT jsonb_object_agg(name, type) FROM foo; ERROR: field name must not be null -- jsonb_object +-- empty object, one dimension +SELECT jsonb_object('{}'); + jsonb_object +-------------- + {} +(1 row) + +-- empty object, two dimensions +SELECT jsonb_object('{}', '{}'); + jsonb_object +-------------- + {} +(1 row) + -- one dimension SELECT jsonb_object('{a,1,b,2,3,NULL,"d e f","a b c"}'); jsonb_object diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql index 0d2c139b4d..39f1b70f4d 100644 --- a/src/test/regress/sql/json.sql +++ b/src/test/regress/sql/json.sql @@ -462,6 +462,12 @@ SELECT json_object_agg(name, type) FROM foo; -- json_object +-- empty object, one dimension +SELECT json_object('{}'); + +-- empty object, two dimensions +SELECT json_object('{}', '{}'); + -- one dimension SELECT json_object('{a,1,b,2,3,NULL,"d e f","a b c"}'); diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index b724f0ab1f..4b24477609 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -352,6 +352,12 @@ SELECT jsonb_object_agg(name, type) FROM foo; -- jsonb_object +-- empty object, one dimension +SELECT jsonb_object('{}'); + +-- empty object, two dimensions +SELECT jsonb_object('{}', '{}'); + -- one dimension SELECT jsonb_object('{a,1,b,2,3,NULL,"d e f","a b c"}'); -- 2.40.0