aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/json.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r--src/backend/utils/adt/json.c166
1 files changed, 72 insertions, 94 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index d1dc87e679f..68132aea4bf 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -1869,10 +1869,10 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
if (PG_ARGISNULL(0))
{
/*
- * Make this StringInfo in a context where it will persist for the
- * duration off the aggregate call. It's only needed for this initial
- * piece, as the StringInfo routines make sure they use the right
- * context to enlarge the object if necessary.
+ * Make the StringInfo in a context where it will persist for the
+ * duration of the aggregate call. Switching context is only needed
+ * for this initial step, as the StringInfo routines make sure they
+ * use the right context to enlarge the object if necessary.
*/
oldcontext = MemoryContextSwitchTo(aggcontext);
state = makeStringInfo();
@@ -1886,56 +1886,43 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
appendStringInfoString(state, ", ");
}
- if (PG_ARGISNULL(1))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("field name must not be null")));
-
- val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
-
/*
- * turn a constant (more or less literal) value that's of unknown type
- * into text. Unknowns come in as a cstring pointer.
+ * Note: since json_object_agg() 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 == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, 1))
- {
- val_type = TEXTOID;
- arg = CStringGetTextDatum(PG_GETARG_POINTER(1));
- }
- else
- {
- arg = PG_GETARG_DATUM(1);
- }
+ val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
- if (val_type == InvalidOid || val_type == UNKNOWNOID)
+ if (val_type == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine data type for argument %d", 1)));
+ if (PG_ARGISNULL(1))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("field name must not be null")));
+
+ arg = PG_GETARG_DATUM(1);
+
add_json(arg, false, state, val_type, true);
appendStringInfoString(state, " : ");
val_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
- /* see comments above */
- if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, 2))
- {
- val_type = TEXTOID;
- if (PG_ARGISNULL(2))
- arg = (Datum) 0;
- else
- arg = CStringGetTextDatum(PG_GETARG_POINTER(2));
- }
- else
- {
- arg = PG_GETARG_DATUM(2);
- }
- if (val_type == InvalidOid || val_type == UNKNOWNOID)
+ if (val_type == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine data type for argument %d", 2)));
+ if (PG_ARGISNULL(2))
+ arg = (Datum) 0;
+ else
+ arg = PG_GETARG_DATUM(2);
+
add_json(arg, PG_ARGISNULL(2), state, val_type, false);
PG_RETURN_POINTER(state);
@@ -1972,7 +1959,7 @@ json_build_object(PG_FUNCTION_ARGS)
int nargs = PG_NARGS();
int i;
Datum arg;
- char *sep = "";
+ const char *sep = "";
StringInfo result;
Oid val_type;
@@ -1988,60 +1975,51 @@ 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))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("argument %d cannot be null", i + 1),
errhint("Object keys should be text.")));
- 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)));
- appendStringInfoString(result, sep);
- sep = ", ";
+ arg = PG_GETARG_DATUM(i);
+
add_json(arg, false, result, val_type, true);
appendStringInfoString(result, " : ");
/* 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)
+
+ 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);
}
@@ -2068,45 +2046,45 @@ json_build_array(PG_FUNCTION_ARGS)
int nargs = PG_NARGS();
int i;
Datum arg;
- char *sep = "";
+ const char *sep = "";
StringInfo result;
Oid val_type;
-
result = makeStringInfo();
appendStringInfoChar(result, '[');
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);
- arg = PG_GETARG_DATUM(i + 1);
- /* see comments in json_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)
+
+ if (val_type == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine data type for argument %d",
i + 1)));
- appendStringInfoString(result, sep);
- sep = ", ";
+
+ if (PG_ARGISNULL(i))
+ arg = (Datum) 0;
+ else
+ arg = PG_GETARG_DATUM(i);
+
add_json(arg, PG_ARGISNULL(i), result, val_type, false);
}
+
appendStringInfoChar(result, ']');
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
-
}
/*