diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index 1ddb42b4d0..614c30bb30 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -2111,10 +2111,73 @@ json_build_object(PG_FUNCTION_ARGS) { int nargs = PG_NARGS(); int i; - Datum arg; const char *sep = ""; StringInfo result; - Oid val_type; + bool variadic = get_fn_expr_variadic(fcinfo->flinfo); + Datum *elements; + bool *nulls; + Oid *val_type; + + /* + * When doing a VARIADIC call, the caller has provided one argument + * made of an array of keys, so deconstruct the array data before + * using it for the next processing. If no VARIADIC call is used, + * just fill in the status data based on all the arguments given by + * the caller. + */ + if (variadic) + { + ArrayType *array_in = PG_GETARG_ARRAYTYPE_P(0); + Oid element_type = ARR_ELEMTYPE(array_in); + bool typbyval; + char typalign; + int16 typlen; + + Assert(PG_NARGS() == 1); + + get_typlenbyvalalign(element_type, + &typlen, &typbyval, &typalign); + deconstruct_array(array_in, element_type, typlen, typbyval, + typalign, &elements, &nulls, + &nargs); + + /* All the elements of the array have the same type */ + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + for (i = 0; i < nargs; i++) + val_type[i] = element_type; + } + else + { + nargs = PG_NARGS(); + nulls = (bool *) palloc0(nargs * sizeof(bool)); + elements = (Datum *) palloc0(nargs * sizeof(Datum)); + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + + for (i = 0; i < nargs; i++) + { + /* + * Note: since json_build_object() is declared as taking type + * "any", the parser will not do any type conversion on + * unknown-type literals (that is, undecorated strings or NULLs). + * Such values will arrive here as type UNKNOWN, which fortunately + * does not matter to us, since unknownout() works fine. + */ + nulls[i] = PG_ARGISNULL(i); + val_type[i] = get_fn_expr_argtype(fcinfo->flinfo, i); + + if (val_type[i] == InvalidOid) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not determine data type for argument %d", + i + 1))); + + /* important for value, key cannot being NULL */ + if (PG_ARGISNULL(i)) + elements[i] = (Datum) 0; + else + elements[i] = PG_GETARG_DATUM(i); + } + } if (nargs % 2 != 0) ereport(ERROR, @@ -2128,52 +2191,22 @@ json_build_object(PG_FUNCTION_ARGS) for (i = 0; i < nargs; i += 2) { - /* - * Note: since json_build_object() is declared as taking type "any", - * the parser will not do any type conversion on unknown-type literals - * (that is, undecorated strings or NULLs). Such values will arrive - * here as type UNKNOWN, which fortunately does not matter to us, - * since unknownout() works fine. - */ appendStringInfoString(result, sep); sep = ", "; /* process key */ - val_type = get_fn_expr_argtype(fcinfo->flinfo, i); - - if (val_type == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine data type for argument %d", - i + 1))); - - if (PG_ARGISNULL(i)) + if (nulls[i]) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("argument %d cannot be null", i + 1), errhint("Object keys should be text."))); - arg = PG_GETARG_DATUM(i); - - add_json(arg, false, result, val_type, true); + add_json(elements[i], false, result, val_type[i], true); appendStringInfoString(result, " : "); /* process value */ - val_type = get_fn_expr_argtype(fcinfo->flinfo, i + 1); - - if (val_type == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine data type for argument %d", - i + 2))); - - if (PG_ARGISNULL(i + 1)) - arg = (Datum) 0; - else - arg = PG_GETARG_DATUM(i + 1); - - add_json(arg, PG_ARGISNULL(i + 1), result, val_type, false); + add_json(elements[i + 1], nulls[i + 1], result, val_type[i + 1], false); } appendStringInfoChar(result, '}'); @@ -2196,12 +2229,74 @@ json_build_object_noargs(PG_FUNCTION_ARGS) Datum json_build_array(PG_FUNCTION_ARGS) { - int nargs = PG_NARGS(); + int nargs; int i; - Datum arg; const char *sep = ""; StringInfo result; - Oid val_type; + bool variadic = get_fn_expr_variadic(fcinfo->flinfo); + Datum *elements; + bool *nulls; + Oid *val_type; + + /* + * When doing a VARIADIC call, the caller has provided one argument + * made of an array of keys, so deconstruct the array data before + * using it for the next processing. If no VARIADIC call is used, + * just fill in the status data based on all the arguments given by + * the caller. + */ + if (variadic) + { + ArrayType *array_in = PG_GETARG_ARRAYTYPE_P(0); + Oid element_type = ARR_ELEMTYPE(array_in); + bool typbyval; + char typalign; + int16 typlen; + + Assert(PG_NARGS() == 1); + + get_typlenbyvalalign(element_type, + &typlen, &typbyval, &typalign); + deconstruct_array(array_in, element_type, typlen, typbyval, + typalign, &elements, &nulls, + &nargs); + + /* All the elements of the array have the same type */ + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + for (i = 0; i < nargs; i++) + val_type[i] = element_type; + } + else + { + nargs = PG_NARGS(); + nulls = (bool *) palloc0(nargs * sizeof(bool)); + elements = (Datum *) palloc0(nargs * sizeof(Datum)); + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + + for (i = 0; i < nargs; i++) + { + nulls[i] = PG_ARGISNULL(i); + val_type[i] = get_fn_expr_argtype(fcinfo->flinfo, i); + + /* + * Note: since json_build_array() is declared as taking type "any", + * the parser will not do any type conversion on unknown-type literals + * (that is, undecorated strings or NULLs). Such values will arrive + * here as type UNKNOWN, which fortunately does not matter to us, + * since unknownout() works fine. + */ + if (val_type == InvalidOid) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not determine data type for argument %d", + i + 1))); + + if (PG_ARGISNULL(i)) + elements[i] = (Datum) 0; + else + elements[i] = PG_GETARG_DATUM(i); + } + } result = makeStringInfo(); @@ -2209,30 +2304,9 @@ json_build_array(PG_FUNCTION_ARGS) for (i = 0; i < nargs; i++) { - /* - * Note: since json_build_array() is declared as taking type "any", - * the parser will not do any type conversion on unknown-type literals - * (that is, undecorated strings or NULLs). Such values will arrive - * here as type UNKNOWN, which fortunately does not matter to us, - * since unknownout() works fine. - */ appendStringInfoString(result, sep); sep = ", "; - - val_type = get_fn_expr_argtype(fcinfo->flinfo, i); - - if (val_type == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine data type for argument %d", - i + 1))); - - if (PG_ARGISNULL(i)) - arg = (Datum) 0; - else - arg = PG_GETARG_DATUM(i); - - add_json(arg, PG_ARGISNULL(i), result, val_type, false); + add_json(elements[i], nulls[i], result, val_type[i], false); } appendStringInfoChar(result, ']'); diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index 771c05120b..fb9580d4f0 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -1171,11 +1171,79 @@ to_jsonb(PG_FUNCTION_ARGS) Datum jsonb_build_object(PG_FUNCTION_ARGS) { - int nargs = PG_NARGS(); + int nargs; int i; - Datum arg; - Oid val_type; JsonbInState result; + bool variadic = get_fn_expr_variadic(fcinfo->flinfo); + Datum *elements; + bool *nulls; + Oid *val_type; + + /* + * When doing a VARIADIC call, the caller has provided one argument + * made of an array of keys, so deconstruct the array data before + * using it for the next processing. If no VARIADIC call is used, + * just fill in the status data based on all the arguments given by + * the caller. + */ + if (variadic) + { + ArrayType *array_in = PG_GETARG_ARRAYTYPE_P(0); + Oid element_type = ARR_ELEMTYPE(array_in); + bool typbyval; + char typalign; + int16 typlen; + + Assert(PG_NARGS() == 1); + + get_typlenbyvalalign(element_type, + &typlen, &typbyval, &typalign); + deconstruct_array(array_in, element_type, typlen, typbyval, + typalign, &elements, &nulls, + &nargs); + + /* All the elements of the array have the same type */ + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + for (i = 0; i < nargs; i++) + val_type[i] = element_type; + } + else + { + nargs = PG_NARGS(); + nulls = (bool *) palloc0(nargs * sizeof(bool)); + elements = (Datum *) palloc0(nargs * sizeof(Datum)); + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + + for (i = 0; i < nargs; i++) + { + nulls[i] = PG_ARGISNULL(i); + val_type[i] = get_fn_expr_argtype(fcinfo->flinfo, i); + + /* + * Turn a constant (more or less literal) value that's of unknown + * type into text. Unknowns come in as a cstring pointer. + */ + if (val_type[i] == UNKNOWNOID && + get_fn_expr_arg_stable(fcinfo->flinfo, i)) + { + val_type[i] = TEXTOID; + + /* important for value, key cannot being NULL */ + if (PG_ARGISNULL(i)) + elements[i] = (Datum) 0; + else + elements[i] = CStringGetTextDatum(PG_GETARG_POINTER(i)); + } + else + elements[i] = PG_GETARG_DATUM(i); + + if (val_type[i] == InvalidOid || val_type[i] == UNKNOWNOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not determine data type for argument %d", + i + 1))); + } + } if (nargs % 2 != 0) ereport(ERROR, @@ -1189,54 +1257,15 @@ jsonb_build_object(PG_FUNCTION_ARGS) for (i = 0; i < nargs; i += 2) { /* process key */ - - if (PG_ARGISNULL(i)) + if (nulls[i]) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("argument %d: key must not be null", i + 1))); - val_type = get_fn_expr_argtype(fcinfo->flinfo, i); - - /* - * turn a constant (more or less literal) value that's of unknown type - * into text. Unknowns come in as a cstring pointer. - */ - if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i)) - { - val_type = TEXTOID; - arg = CStringGetTextDatum(PG_GETARG_POINTER(i)); - } - else - { - arg = PG_GETARG_DATUM(i); - } - if (val_type == InvalidOid || val_type == UNKNOWNOID) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine data type for argument %d", i + 1))); - add_jsonb(arg, false, &result, val_type, true); + add_jsonb(elements[i], false, &result, val_type[i], true); /* process value */ - - val_type = get_fn_expr_argtype(fcinfo->flinfo, i + 1); - /* see comments above */ - if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i + 1)) - { - val_type = TEXTOID; - if (PG_ARGISNULL(i + 1)) - arg = (Datum) 0; - else - arg = CStringGetTextDatum(PG_GETARG_POINTER(i + 1)); - } - else - { - arg = PG_GETARG_DATUM(i + 1); - } - if (val_type == InvalidOid || val_type == UNKNOWNOID) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine data type for argument %d", i + 2))); - add_jsonb(arg, PG_ARGISNULL(i + 1), &result, val_type, false); + add_jsonb(elements[i + 1], nulls[i + 1], &result, val_type[i + 1], false); } result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL); @@ -1266,39 +1295,83 @@ jsonb_build_object_noargs(PG_FUNCTION_ARGS) Datum jsonb_build_array(PG_FUNCTION_ARGS) { - int nargs = PG_NARGS(); + int nargs; int i; - Datum arg; - Oid val_type; JsonbInState result; + bool variadic = get_fn_expr_variadic(fcinfo->flinfo); + Datum *elements; + bool *nulls; + Oid *val_type; - memset(&result, 0, sizeof(JsonbInState)); - - result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL); - - for (i = 0; i < nargs; i++) + /* + * When doing a VARIADIC call, the caller has provided one argument + * made of an array of keys, so deconstruct the array data before + * using it for the next processing. If no VARIADIC call is used, + * just fill in the status data based on all the arguments given by + * the caller. + */ + if (variadic) { - val_type = get_fn_expr_argtype(fcinfo->flinfo, i); - /* see comments in jsonb_build_object above */ - if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i)) + ArrayType *array_in = PG_GETARG_ARRAYTYPE_P(0); + Oid element_type = ARR_ELEMTYPE(array_in); + bool typbyval; + char typalign; + int16 typlen; + + Assert(PG_NARGS() == 1); + + get_typlenbyvalalign(element_type, + &typlen, &typbyval, &typalign); + deconstruct_array(array_in, element_type, typlen, typbyval, + typalign, &elements, &nulls, + &nargs); + + /* All the elements of the array have the same type */ + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + for (i = 0; i < nargs; i++) + val_type[i] = element_type; + } + else + { + nargs = PG_NARGS(); + nulls = (bool *) palloc0(nargs * sizeof(bool)); + elements = (Datum *) palloc0(nargs * sizeof(Datum)); + val_type = (Oid *) palloc0(nargs * sizeof(Oid)); + + for (i = 0; i < nargs; i++) { - val_type = TEXTOID; - if (PG_ARGISNULL(i)) - arg = (Datum) 0; + nulls[i] = PG_ARGISNULL(i); + val_type[i] = get_fn_expr_argtype(fcinfo->flinfo, i); + + /* see comments in jsonb_build_object above */ + if (val_type[i] == UNKNOWNOID && + get_fn_expr_arg_stable(fcinfo->flinfo, i)) + { + val_type[i] = TEXTOID; + + if (PG_ARGISNULL(i)) + elements[i] = (Datum) 0; + else + elements[i] = CStringGetTextDatum(PG_GETARG_POINTER(i)); + } else - arg = CStringGetTextDatum(PG_GETARG_POINTER(i)); - } - else - { - arg = PG_GETARG_DATUM(i); + elements[i] = PG_GETARG_DATUM(i); + + if (val_type[i] == InvalidOid || val_type[i] == UNKNOWNOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not determine data type for argument %d", + i + 1))); } - if (val_type == InvalidOid || val_type == UNKNOWNOID) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine data type for argument %d", i + 1))); - add_jsonb(arg, PG_ARGISNULL(i), &result, val_type, false); } + memset(&result, 0, sizeof(JsonbInState)); + + result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL); + + for (i = 0; i < nargs; i++) + add_jsonb(elements[i], nulls[i], &result, val_type[i], false); + result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL); PG_RETURN_POINTER(JsonbValueToJsonb(result.res)); diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out index d7abae9867..de13619115 100644 --- a/src/test/regress/expected/json.out +++ b/src/test/regress/expected/json.out @@ -1864,6 +1864,42 @@ SELECT json_build_array('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": ["a", 1, "b", 1.2, "c", true, "d", null, "e", {"x": 3, "y": [1,2,3]}] (1 row) +SELECT json_build_array('a', NULL); -- ok + json_build_array +------------------ + ["a", null] +(1 row) + +SELECT json_build_array(VARIADIC '{a,b,c}'::text[]); -- ok + json_build_array +------------------ + ["a", "b", "c"] +(1 row) + +SELECT json_build_array(VARIADIC ARRAY['a', NULL]::text[]); -- ok + json_build_array +------------------ + ["a", null] +(1 row) + +SELECT json_build_array(VARIADIC '{1,2,3,4}'::text[]); -- ok + json_build_array +---------------------- + ["1", "2", "3", "4"] +(1 row) + +SELECT json_build_array(VARIADIC '{1,2,3,4}'::int[]); -- ok + json_build_array +------------------ + [1, 2, 3, 4] +(1 row) + +SELECT json_build_array(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok + json_build_array +-------------------- + [1, 4, 2, 5, 3, 6] +(1 row) + SELECT json_build_object('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}'); json_build_object ---------------------------------------------------------------------------- @@ -1879,6 +1915,53 @@ SELECT json_build_object( {"a" : {"b" : false, "c" : 99}, "d" : {"e" : [9,8,7], "f" : {"relkind":"r","name":"pg_class"}}} (1 row) +SELECT json_build_object('{a,b,c}'::text[]); -- error +ERROR: argument list must have even number of elements +HINT: The arguments of json_build_object() must consist of alternating keys and values. +SELECT json_build_object('{a,b,c}'::text[], '{d,e,f}'::text[]); -- error, key cannot be array +ERROR: key value must be scalar, not array, composite, or json +SELECT json_build_object('a', 'b', 'c'); -- error +ERROR: argument list must have even number of elements +HINT: The arguments of json_build_object() must consist of alternating keys and values. +SELECT json_build_object(NULL, 'a'); -- error, key cannot be NULL +ERROR: argument 1 cannot be null +HINT: Object keys should be text. +SELECT json_build_object('a', NULL); -- ok + json_build_object +------------------- + {"a" : null} +(1 row) + +SELECT json_build_object(VARIADIC '{a,b,c}'::text[]); -- error +ERROR: argument list must have even number of elements +HINT: The arguments of json_build_object() must consist of alternating keys and values. +SELECT json_build_object(VARIADIC ARRAY['a', NULL]::text[]); -- ok + json_build_object +------------------- + {"a" : null} +(1 row) + +SELECT json_build_object(VARIADIC ARRAY[NULL, 'a']::text[]); -- error, key cannot be NULL +ERROR: argument 1 cannot be null +HINT: Object keys should be text. +SELECT json_build_object(VARIADIC '{1,2,3,4}'::text[]); -- ok + json_build_object +------------------------ + {"1" : "2", "3" : "4"} +(1 row) + +SELECT json_build_object(VARIADIC '{1,2,3,4}'::int[]); -- ok + json_build_object +-------------------- + {"1" : 2, "3" : 4} +(1 row) + +SELECT json_build_object(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok + json_build_object +----------------------------- + {"1" : 4, "2" : 5, "3" : 6} +(1 row) + -- empty objects/arrays SELECT json_build_array(); json_build_array diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index dcea6a47a3..12b4709b10 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -1345,6 +1345,42 @@ SELECT jsonb_build_array('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": ["a", 1, "b", 1.2, "c", true, "d", null, "e", {"x": 3, "y": [1, 2, 3]}] (1 row) +SELECT jsonb_build_array('a', NULL); -- ok + jsonb_build_array +------------------- + ["a", null] +(1 row) + +SELECT jsonb_build_array(VARIADIC '{a,b,c}'::text[]); -- ok + jsonb_build_array +------------------- + ["a", "b", "c"] +(1 row) + +SELECT jsonb_build_array(VARIADIC ARRAY['a', NULL]::text[]); -- ok + jsonb_build_array +------------------- + ["a", null] +(1 row) + +SELECT jsonb_build_array(VARIADIC '{1,2,3,4}'::text[]); -- ok + jsonb_build_array +---------------------- + ["1", "2", "3", "4"] +(1 row) + +SELECT jsonb_build_array(VARIADIC '{1,2,3,4}'::int[]); -- ok + jsonb_build_array +------------------- + [1, 2, 3, 4] +(1 row) + +SELECT jsonb_build_array(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok + jsonb_build_array +-------------------- + [1, 4, 2, 5, 3, 6] +(1 row) + SELECT jsonb_build_object('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}'); jsonb_build_object ------------------------------------------------------------------------- @@ -1360,6 +1396,48 @@ SELECT jsonb_build_object( {"a": {"b": false, "c": 99}, "d": {"e": [9, 8, 7], "f": {"name": "pg_class", "relkind": "r"}}} (1 row) +SELECT jsonb_build_object('{a,b,c}'::text[]); -- error +ERROR: invalid number of arguments: object must be matched key value pairs +SELECT jsonb_build_object('{a,b,c}'::text[], '{d,e,f}'::text[]); -- error, key cannot be array +ERROR: key value must be scalar, not array, composite, or json +SELECT jsonb_build_object('a', 'b', 'c'); -- error +ERROR: invalid number of arguments: object must be matched key value pairs +SELECT jsonb_build_object(NULL, 'a'); -- error, key cannot be NULL +ERROR: argument 1: key must not be null +SELECT jsonb_build_object('a', NULL); -- ok + jsonb_build_object +-------------------- + {"a": null} +(1 row) + +SELECT jsonb_build_object(VARIADIC '{a,b,c}'::text[]); -- error +ERROR: invalid number of arguments: object must be matched key value pairs +SELECT jsonb_build_object(VARIADIC ARRAY['a', NULL]::text[]); -- ok + jsonb_build_object +-------------------- + {"a": null} +(1 row) + +SELECT jsonb_build_object(VARIADIC ARRAY[NULL, 'a']::text[]); -- error, key cannot be NULL +ERROR: argument 1: key must not be null +SELECT jsonb_build_object(VARIADIC '{1,2,3,4}'::text[]); -- ok + jsonb_build_object +---------------------- + {"1": "2", "3": "4"} +(1 row) + +SELECT jsonb_build_object(VARIADIC '{1,2,3,4}'::int[]); -- ok + jsonb_build_object +-------------------- + {"1": 2, "3": 4} +(1 row) + +SELECT jsonb_build_object(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok + jsonb_build_object +-------------------------- + {"1": 4, "2": 5, "3": 6} +(1 row) + -- empty objects/arrays SELECT jsonb_build_array(); jsonb_build_array diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql index 506e3a8fc5..b4f1786caf 100644 --- a/src/test/regress/sql/json.sql +++ b/src/test/regress/sql/json.sql @@ -569,6 +569,12 @@ select value, json_typeof(value) -- json_build_array, json_build_object, json_object_agg SELECT json_build_array('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}'); +SELECT json_build_array('a', NULL); -- ok +SELECT json_build_array(VARIADIC '{a,b,c}'::text[]); -- ok +SELECT json_build_array(VARIADIC ARRAY['a', NULL]::text[]); -- ok +SELECT json_build_array(VARIADIC '{1,2,3,4}'::text[]); -- ok +SELECT json_build_array(VARIADIC '{1,2,3,4}'::int[]); -- ok +SELECT json_build_array(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok SELECT json_build_object('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}'); @@ -576,6 +582,17 @@ SELECT json_build_object( 'a', json_build_object('b',false,'c',99), 'd', json_build_object('e',array[9,8,7]::int[], 'f', (select row_to_json(r) from ( select relkind, oid::regclass as name from pg_class where relname = 'pg_class') r))); +SELECT json_build_object('{a,b,c}'::text[]); -- error +SELECT json_build_object('{a,b,c}'::text[], '{d,e,f}'::text[]); -- error, key cannot be array +SELECT json_build_object('a', 'b', 'c'); -- error +SELECT json_build_object(NULL, 'a'); -- error, key cannot be NULL +SELECT json_build_object('a', NULL); -- ok +SELECT json_build_object(VARIADIC '{a,b,c}'::text[]); -- error +SELECT json_build_object(VARIADIC ARRAY['a', NULL]::text[]); -- ok +SELECT json_build_object(VARIADIC ARRAY[NULL, 'a']::text[]); -- error, key cannot be NULL +SELECT json_build_object(VARIADIC '{1,2,3,4}'::text[]); -- ok +SELECT json_build_object(VARIADIC '{1,2,3,4}'::int[]); -- ok +SELECT json_build_object(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok -- empty objects/arrays SELECT json_build_array(); diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 57fff3bfb3..078e331658 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -313,6 +313,12 @@ SELECT jsonb_typeof('"1.0"') AS string; -- jsonb_build_array, jsonb_build_object, jsonb_object_agg SELECT jsonb_build_array('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}'); +SELECT jsonb_build_array('a', NULL); -- ok +SELECT jsonb_build_array(VARIADIC '{a,b,c}'::text[]); -- ok +SELECT jsonb_build_array(VARIADIC ARRAY['a', NULL]::text[]); -- ok +SELECT jsonb_build_array(VARIADIC '{1,2,3,4}'::text[]); -- ok +SELECT jsonb_build_array(VARIADIC '{1,2,3,4}'::int[]); -- ok +SELECT jsonb_build_array(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok SELECT jsonb_build_object('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}'); @@ -320,7 +326,17 @@ SELECT jsonb_build_object( 'a', jsonb_build_object('b',false,'c',99), 'd', jsonb_build_object('e',array[9,8,7]::int[], 'f', (select row_to_json(r) from ( select relkind, oid::regclass as name from pg_class where relname = 'pg_class') r))); - +SELECT jsonb_build_object('{a,b,c}'::text[]); -- error +SELECT jsonb_build_object('{a,b,c}'::text[], '{d,e,f}'::text[]); -- error, key cannot be array +SELECT jsonb_build_object('a', 'b', 'c'); -- error +SELECT jsonb_build_object(NULL, 'a'); -- error, key cannot be NULL +SELECT jsonb_build_object('a', NULL); -- ok +SELECT jsonb_build_object(VARIADIC '{a,b,c}'::text[]); -- error +SELECT jsonb_build_object(VARIADIC ARRAY['a', NULL]::text[]); -- ok +SELECT jsonb_build_object(VARIADIC ARRAY[NULL, 'a']::text[]); -- error, key cannot be NULL +SELECT jsonb_build_object(VARIADIC '{1,2,3,4}'::text[]); -- ok +SELECT jsonb_build_object(VARIADIC '{1,2,3,4}'::int[]); -- ok +SELECT jsonb_build_object(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok -- empty objects/arrays SELECT jsonb_build_array();