Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 92f57c9

Browse files
committed
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.
1 parent 495cadd commit 92f57c9

File tree

1 file changed

+72
-94
lines changed

1 file changed

+72
-94
lines changed

src/backend/utils/adt/json.c

+72-94
Original file line numberDiff line numberDiff line change
@@ -1869,10 +1869,10 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
18691869
if (PG_ARGISNULL(0))
18701870
{
18711871
/*
1872-
* Make this StringInfo in a context where it will persist for the
1873-
* duration off the aggregate call. It's only needed for this initial
1874-
* piece, as the StringInfo routines make sure they use the right
1875-
* context to enlarge the object if necessary.
1872+
* Make the StringInfo in a context where it will persist for the
1873+
* duration of the aggregate call. Switching context is only needed
1874+
* for this initial step, as the StringInfo routines make sure they
1875+
* use the right context to enlarge the object if necessary.
18761876
*/
18771877
oldcontext = MemoryContextSwitchTo(aggcontext);
18781878
state = makeStringInfo();
@@ -1886,56 +1886,43 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
18861886
appendStringInfoString(state, ", ");
18871887
}
18881888

1889-
if (PG_ARGISNULL(1))
1890-
ereport(ERROR,
1891-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1892-
errmsg("field name must not be null")));
1893-
1894-
val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1895-
18961889
/*
1897-
* turn a constant (more or less literal) value that's of unknown type
1898-
* into text. Unknowns come in as a cstring pointer.
1890+
* Note: since json_object_agg() is declared as taking type "any", the
1891+
* parser will not do any type conversion on unknown-type literals (that
1892+
* is, undecorated strings or NULLs). Such values will arrive here as
1893+
* type UNKNOWN, which fortunately does not matter to us, since
1894+
* unknownout() works fine.
18991895
*/
1900-
if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, 1))
1901-
{
1902-
val_type = TEXTOID;
1903-
arg = CStringGetTextDatum(PG_GETARG_POINTER(1));
1904-
}
1905-
else
1906-
{
1907-
arg = PG_GETARG_DATUM(1);
1908-
}
1896+
val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
19091897

1910-
if (val_type == InvalidOid || val_type == UNKNOWNOID)
1898+
if (val_type == InvalidOid)
19111899
ereport(ERROR,
19121900
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
19131901
errmsg("could not determine data type for argument %d", 1)));
19141902

1903+
if (PG_ARGISNULL(1))
1904+
ereport(ERROR,
1905+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1906+
errmsg("field name must not be null")));
1907+
1908+
arg = PG_GETARG_DATUM(1);
1909+
19151910
add_json(arg, false, state, val_type, true);
19161911

19171912
appendStringInfoString(state, " : ");
19181913

19191914
val_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1920-
/* see comments above */
1921-
if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, 2))
1922-
{
1923-
val_type = TEXTOID;
1924-
if (PG_ARGISNULL(2))
1925-
arg = (Datum) 0;
1926-
else
1927-
arg = CStringGetTextDatum(PG_GETARG_POINTER(2));
1928-
}
1929-
else
1930-
{
1931-
arg = PG_GETARG_DATUM(2);
1932-
}
19331915

1934-
if (val_type == InvalidOid || val_type == UNKNOWNOID)
1916+
if (val_type == InvalidOid)
19351917
ereport(ERROR,
19361918
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
19371919
errmsg("could not determine data type for argument %d", 2)));
19381920

1921+
if (PG_ARGISNULL(2))
1922+
arg = (Datum) 0;
1923+
else
1924+
arg = PG_GETARG_DATUM(2);
1925+
19391926
add_json(arg, PG_ARGISNULL(2), state, val_type, false);
19401927

19411928
PG_RETURN_POINTER(state);
@@ -1972,7 +1959,7 @@ json_build_object(PG_FUNCTION_ARGS)
19721959
int nargs = PG_NARGS();
19731960
int i;
19741961
Datum arg;
1975-
char *sep = "";
1962+
const char *sep = "";
19761963
StringInfo result;
19771964
Oid val_type;
19781965

@@ -1988,60 +1975,51 @@ json_build_object(PG_FUNCTION_ARGS)
19881975

19891976
for (i = 0; i < nargs; i += 2)
19901977
{
1978+
/*
1979+
* Note: since json_build_object() is declared as taking type "any",
1980+
* the parser will not do any type conversion on unknown-type literals
1981+
* (that is, undecorated strings or NULLs). Such values will arrive
1982+
* here as type UNKNOWN, which fortunately does not matter to us,
1983+
* since unknownout() works fine.
1984+
*/
1985+
appendStringInfoString(result, sep);
1986+
sep = ", ";
1987+
19911988
/* process key */
1989+
val_type = get_fn_expr_argtype(fcinfo->flinfo, i);
1990+
1991+
if (val_type == InvalidOid)
1992+
ereport(ERROR,
1993+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1994+
errmsg("could not determine data type for argument %d",
1995+
i + 1)));
19921996

19931997
if (PG_ARGISNULL(i))
19941998
ereport(ERROR,
19951999
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
19962000
errmsg("argument %d cannot be null", i + 1),
19972001
errhint("Object keys should be text.")));
1998-
val_type = get_fn_expr_argtype(fcinfo->flinfo, i);
19992002

2000-
/*
2001-
* turn a constant (more or less literal) value that's of unknown type
2002-
* into text. Unknowns come in as a cstring pointer.
2003-
*/
2004-
if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i))
2005-
{
2006-
val_type = TEXTOID;
2007-
arg = CStringGetTextDatum(PG_GETARG_POINTER(i));
2008-
}
2009-
else
2010-
{
2011-
arg = PG_GETARG_DATUM(i);
2012-
}
2013-
if (val_type == InvalidOid || val_type == UNKNOWNOID)
2014-
ereport(ERROR,
2015-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2016-
errmsg("could not determine data type for argument %d",
2017-
i + 1)));
2018-
appendStringInfoString(result, sep);
2019-
sep = ", ";
2003+
arg = PG_GETARG_DATUM(i);
2004+
20202005
add_json(arg, false, result, val_type, true);
20212006

20222007
appendStringInfoString(result, " : ");
20232008

20242009
/* process value */
2025-
20262010
val_type = get_fn_expr_argtype(fcinfo->flinfo, i + 1);
2027-
/* see comments above */
2028-
if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i + 1))
2029-
{
2030-
val_type = TEXTOID;
2031-
if (PG_ARGISNULL(i + 1))
2032-
arg = (Datum) 0;
2033-
else
2034-
arg = CStringGetTextDatum(PG_GETARG_POINTER(i + 1));
2035-
}
2036-
else
2037-
{
2038-
arg = PG_GETARG_DATUM(i + 1);
2039-
}
2040-
if (val_type == InvalidOid || val_type == UNKNOWNOID)
2011+
2012+
if (val_type == InvalidOid)
20412013
ereport(ERROR,
20422014
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
20432015
errmsg("could not determine data type for argument %d",
20442016
i + 2)));
2017+
2018+
if (PG_ARGISNULL(i + 1))
2019+
arg = (Datum) 0;
2020+
else
2021+
arg = PG_GETARG_DATUM(i + 1);
2022+
20452023
add_json(arg, PG_ARGISNULL(i + 1), result, val_type, false);
20462024
}
20472025

@@ -2068,45 +2046,45 @@ json_build_array(PG_FUNCTION_ARGS)
20682046
int nargs = PG_NARGS();
20692047
int i;
20702048
Datum arg;
2071-
char *sep = "";
2049+
const char *sep = "";
20722050
StringInfo result;
20732051
Oid val_type;
20742052

2075-
20762053
result = makeStringInfo();
20772054

20782055
appendStringInfoChar(result, '[');
20792056

20802057
for (i = 0; i < nargs; i++)
20812058
{
2059+
/*
2060+
* Note: since json_build_array() is declared as taking type "any",
2061+
* the parser will not do any type conversion on unknown-type literals
2062+
* (that is, undecorated strings or NULLs). Such values will arrive
2063+
* here as type UNKNOWN, which fortunately does not matter to us,
2064+
* since unknownout() works fine.
2065+
*/
2066+
appendStringInfoString(result, sep);
2067+
sep = ", ";
2068+
20822069
val_type = get_fn_expr_argtype(fcinfo->flinfo, i);
2083-
arg = PG_GETARG_DATUM(i + 1);
2084-
/* see comments in json_build_object above */
2085-
if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i))
2086-
{
2087-
val_type = TEXTOID;
2088-
if (PG_ARGISNULL(i))
2089-
arg = (Datum) 0;
2090-
else
2091-
arg = CStringGetTextDatum(PG_GETARG_POINTER(i));
2092-
}
2093-
else
2094-
{
2095-
arg = PG_GETARG_DATUM(i);
2096-
}
2097-
if (val_type == InvalidOid || val_type == UNKNOWNOID)
2070+
2071+
if (val_type == InvalidOid)
20982072
ereport(ERROR,
20992073
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
21002074
errmsg("could not determine data type for argument %d",
21012075
i + 1)));
2102-
appendStringInfoString(result, sep);
2103-
sep = ", ";
2076+
2077+
if (PG_ARGISNULL(i))
2078+
arg = (Datum) 0;
2079+
else
2080+
arg = PG_GETARG_DATUM(i);
2081+
21042082
add_json(arg, PG_ARGISNULL(i), result, val_type, false);
21052083
}
2084+
21062085
appendStringInfoChar(result, ']');
21072086

21082087
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
2109-
21102088
}
21112089

21122090
/*

0 commit comments

Comments
 (0)