aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/utils/adt/json.c84
-rw-r--r--src/backend/utils/adt/jsonb.c97
2 files changed, 51 insertions, 130 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index eafca14be4d..a25e7058f74 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -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"
@@ -2106,10 +2107,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,
@@ -2123,52 +2131,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, '}');
@@ -2191,12 +2169,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();
@@ -2204,30 +2189,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, ']');
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index a39d084ce8f..70ee928e58d 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/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"
@@ -1170,16 +1171,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));
@@ -1188,54 +1197,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);
@@ -1265,38 +1235,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);