Commit 92f57c9a authored by Tom Lane's avatar Tom Lane

Clean up handling of unknown-type inputs in json_build_object and friends.

There's actually no need for any special case for unknown-type literals,
since we only need to push the value through its output function and
unknownout() works fine.  The code that was here was completely bizarre
anyway, and would fail outright in cases that should work, not to mention
suffering from some copy-and-paste bugs.
parent 495cadda
......@@ -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));
}
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment