]> granicus.if.org Git - postgresql/commitdiff
Process variadic arguments consistently in json functions
authorAndrew Dunstan <andrew@dunslane.net>
Wed, 25 Oct 2017 11:34:00 +0000 (07:34 -0400)
committerAndrew Dunstan <andrew@dunslane.net>
Wed, 25 Oct 2017 11:34:00 +0000 (07:34 -0400)
json_build_object and json_build_array and the jsonb equivalents did not
correctly process explicit VARIADIC arguments. They are modified to use
the new extract_variadic_args() utility function which abstracts away
the details of the call method.

Michael Paquier, reviewed by Tom Lane and Dmitry Dolgov.

Backpatch to 9.5 for the jsonb fixes and 9.4 for the json fixes, as
that's where they originated.

src/backend/utils/adt/json.c
src/backend/utils/adt/jsonb.c
src/test/regress/expected/json.out
src/test/regress/expected/jsonb.out
src/test/regress/sql/json.sql
src/test/regress/sql/jsonb.sql

index 1ddb42b4d08c5ddf7aca75f13603e2c07b3def1b..baf1178995c9f212cf456acef08bab242b27725b 100644 (file)
@@ -17,6 +17,7 @@
 #include "access/transam.h"
 #include "catalog/pg_type.h"
 #include "executor/spi.h"
+#include "funcapi.h"
 #include "lib/stringinfo.h"
 #include "libpq/pqformat.h"
 #include "mb/pg_wchar.h"
@@ -2111,10 +2112,17 @@ json_build_object(PG_FUNCTION_ARGS)
 {
        int                     nargs = PG_NARGS();
        int                     i;
-       Datum           arg;
        const char *sep = "";
        StringInfo      result;
-       Oid                     val_type;
+       Datum      *args;
+       bool       *nulls;
+       Oid                *types;
+
+       /* fetch argument values to build the object */
+       nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
+
+       if (nargs < 0)
+               PG_RETURN_NULL();
 
        if (nargs % 2 != 0)
                ereport(ERROR,
@@ -2128,52 +2136,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(args[i], false, result, types[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(args[i + 1], nulls[i + 1], result, types[i + 1], false);
        }
 
        appendStringInfoChar(result, '}');
@@ -2196,12 +2174,19 @@ 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;
+       Datum      *args;
+       bool       *nulls;
+       Oid                *types;
+
+       /* fetch argument values to build the array */
+       nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
+
+       if (nargs < 0)
+               PG_RETURN_NULL();
 
        result = makeStringInfo();
 
@@ -2209,30 +2194,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(args[i], nulls[i], result, types[i], false);
        }
 
        appendStringInfoChar(result, ']');
index 771c05120bb56cd9a70c2fcb51d9f7474ba7b6e1..7185b4cce53bcb338824136f8e06691376c00199 100644 (file)
@@ -3,7 +3,7 @@
  * jsonb.c
  *             I/O routines for jsonb type
  *
- * Copyright (c) 2014-2017, PostgreSQL Global Development Group
+ * COPYRIGHT (c) 2014-2017, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
  *       src/backend/utils/adt/jsonb.c
@@ -16,6 +16,7 @@
 #include "access/htup_details.h"
 #include "access/transam.h"
 #include "catalog/pg_type.h"
+#include "funcapi.h"
 #include "libpq/pqformat.h"
 #include "parser/parse_coerce.h"
 #include "utils/builtins.h"
@@ -1171,16 +1172,24 @@ 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;
+       Datum      *args;
+       bool       *nulls;
+       Oid                *types;
+
+       /* build argument values to build the object */
+       nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
+
+       if (nargs < 0)
+               PG_RETURN_NULL();
 
        if (nargs % 2 != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                errmsg("invalid number of arguments: object must be matched key value pairs")));
+                                errmsg("argument list must have even number of elements"),
+                                errhint("The arguments of jsonb_build_object() must consist of alternating keys and values.")));
 
        memset(&result, 0, sizeof(JsonbInState));
 
@@ -1189,54 +1198,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(args[i], false, &result, types[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(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
        }
 
        result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
@@ -1266,38 +1236,25 @@ 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;
+       Datum      *args;
+       bool       *nulls;
+       Oid                *types;
+
+       /* build argument values to build the array */
+       nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
+
+       if (nargs < 0)
+               PG_RETURN_NULL();
 
        memset(&result, 0, sizeof(JsonbInState));
 
        result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
 
        for (i = 0; i < nargs; i++)
-       {
-               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))
-               {
-                       val_type = TEXTOID;
-                       if (PG_ARGISNULL(i))
-                               arg = (Datum) 0;
-                       else
-                               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, PG_ARGISNULL(i), &result, val_type, false);
-       }
+               add_jsonb(args[i], nulls[i], &result, types[i], false);
 
        result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
 
index d7abae9867faa8db1ed6f738bdc8924747080517..9fc91f8d12142f5a928ec4264226834720e23c30 100644 (file)
@@ -1864,6 +1864,54 @@ 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 NULL::text[]); -- ok
+ json_build_array 
+------------------
+(1 row)
+
+SELECT json_build_array(VARIADIC '{}'::text[]); -- ok
+ json_build_array 
+------------------
+ []
+(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 +1927,65 @@ 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 NULL::text[]); -- ok
+ json_build_object 
+-------------------
+(1 row)
+
+SELECT json_build_object(VARIADIC '{}'::text[]); -- ok
+ json_build_object 
+-------------------
+ {}
+(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 
index dcea6a47a367e9700b58784873d02b195e33f824..eeac2a13c710a4aa32477892b2cdfd5709da3781 100644 (file)
@@ -1345,6 +1345,54 @@ 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 NULL::text[]); -- ok
+ jsonb_build_array 
+-------------------
+(1 row)
+
+SELECT jsonb_build_array(VARIADIC '{}'::text[]); -- ok
+ jsonb_build_array 
+-------------------
+ []
+(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 +1408,63 @@ 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:  argument list must have even number of elements
+HINT:  The arguments of jsonb_build_object() must consist of alternating keys and values.
+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:  argument list must have even number of elements
+HINT:  The arguments of jsonb_build_object() must consist of alternating keys and values.
+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 NULL::text[]); -- ok
+ jsonb_build_object 
+--------------------
+(1 row)
+
+SELECT jsonb_build_object(VARIADIC '{}'::text[]); -- ok
+ jsonb_build_object 
+--------------------
+ {}
+(1 row)
+
+SELECT jsonb_build_object(VARIADIC '{a,b,c}'::text[]); -- error
+ERROR:  argument list must have even number of elements
+HINT:  The arguments of jsonb_build_object() must consist of alternating keys and values.
+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 
index 506e3a8fc541667e6772c7b031ab740434424d8e..598498d40a294a48d4e4756df5f163b06d15ff23 100644 (file)
@@ -569,6 +569,14 @@ 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 NULL::text[]); -- ok
+SELECT json_build_array(VARIADIC '{}'::text[]); -- 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 +584,19 @@ 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 NULL::text[]); -- ok
+SELECT json_build_object(VARIADIC '{}'::text[]); -- 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();
index 57fff3bfb3e6d05c9174995f9555c90201182aeb..d0e3f2a1f6d7823f3083d35e2ba6010bffb54c79 100644 (file)
@@ -313,6 +313,14 @@ 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 NULL::text[]); -- ok
+SELECT jsonb_build_array(VARIADIC '{}'::text[]); -- 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 +328,19 @@ 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 NULL::text[]); -- ok
+SELECT jsonb_build_object(VARIADIC '{}'::text[]); -- 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();