mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Get rid of more cases of the "must detoast before output function" meme.
I missed that json.c was doing this too, because for some bizarre reason it wasn't doing it adjacent to the output function call.
This commit is contained in:
parent
b006f4ddb9
commit
e36ce0c7f7
@ -1425,8 +1425,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
|||||||
|
|
||||||
for (i = 0; i < tupdesc->natts; i++)
|
for (i = 0; i < tupdesc->natts; i++)
|
||||||
{
|
{
|
||||||
Datum val,
|
Datum val;
|
||||||
origval;
|
|
||||||
bool isnull;
|
bool isnull;
|
||||||
char *attname;
|
char *attname;
|
||||||
TYPCATEGORY tcategory;
|
TYPCATEGORY tcategory;
|
||||||
@ -1445,7 +1444,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
|||||||
escape_json(result, attname);
|
escape_json(result, attname);
|
||||||
appendStringInfoChar(result, ':');
|
appendStringInfoChar(result, ':');
|
||||||
|
|
||||||
origval = heap_getattr(tuple, i + 1, tupdesc, &isnull);
|
val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
|
||||||
|
|
||||||
getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
|
getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
|
||||||
&typoutput, &typisvarlena);
|
&typoutput, &typisvarlena);
|
||||||
@ -1480,20 +1479,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
|||||||
else
|
else
|
||||||
tcategory = TypeCategory(tupdesc->attrs[i]->atttypid);
|
tcategory = TypeCategory(tupdesc->attrs[i]->atttypid);
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have a toasted datum, forcibly detoast it here to avoid
|
|
||||||
* memory leakage inside the type's output routine.
|
|
||||||
*/
|
|
||||||
if (typisvarlena && !isnull)
|
|
||||||
val = PointerGetDatum(PG_DETOAST_DATUM(origval));
|
|
||||||
else
|
|
||||||
val = origval;
|
|
||||||
|
|
||||||
datum_to_json(val, isnull, result, tcategory, typoutput);
|
datum_to_json(val, isnull, result, tcategory, typoutput);
|
||||||
|
|
||||||
/* Clean up detoasted copy, if any */
|
|
||||||
if (val != origval)
|
|
||||||
pfree(DatumGetPointer(val));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appendStringInfoChar(result, '}');
|
appendStringInfoChar(result, '}');
|
||||||
@ -1572,10 +1558,9 @@ row_to_json_pretty(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
to_json(PG_FUNCTION_ARGS)
|
to_json(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
Datum val = PG_GETARG_DATUM(0);
|
||||||
Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
|
Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
|
||||||
StringInfo result;
|
StringInfo result;
|
||||||
Datum orig_val,
|
|
||||||
val;
|
|
||||||
TYPCATEGORY tcategory;
|
TYPCATEGORY tcategory;
|
||||||
Oid typoutput;
|
Oid typoutput;
|
||||||
bool typisvarlena;
|
bool typisvarlena;
|
||||||
@ -1586,11 +1571,8 @@ to_json(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("could not determine input data type")));
|
errmsg("could not determine input data type")));
|
||||||
|
|
||||||
|
|
||||||
result = makeStringInfo();
|
result = makeStringInfo();
|
||||||
|
|
||||||
orig_val = PG_ARGISNULL(0) ? (Datum) 0 : PG_GETARG_DATUM(0);
|
|
||||||
|
|
||||||
getTypeOutputInfo(val_type, &typoutput, &typisvarlena);
|
getTypeOutputInfo(val_type, &typoutput, &typisvarlena);
|
||||||
|
|
||||||
if (val_type > FirstNormalObjectId)
|
if (val_type > FirstNormalObjectId)
|
||||||
@ -1623,21 +1605,8 @@ to_json(PG_FUNCTION_ARGS)
|
|||||||
else
|
else
|
||||||
tcategory = TypeCategory(val_type);
|
tcategory = TypeCategory(val_type);
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have a toasted datum, forcibly detoast it here to avoid memory
|
|
||||||
* leakage inside the type's output routine.
|
|
||||||
*/
|
|
||||||
if (typisvarlena && orig_val != (Datum) 0)
|
|
||||||
val = PointerGetDatum(PG_DETOAST_DATUM(orig_val));
|
|
||||||
else
|
|
||||||
val = orig_val;
|
|
||||||
|
|
||||||
datum_to_json(val, false, result, tcategory, typoutput);
|
datum_to_json(val, false, result, tcategory, typoutput);
|
||||||
|
|
||||||
/* Clean up detoasted copy, if any */
|
|
||||||
if (val != orig_val)
|
|
||||||
pfree(DatumGetPointer(val));
|
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(cstring_to_text(result->data));
|
PG_RETURN_TEXT_P(cstring_to_text(result->data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1651,8 +1620,7 @@ json_agg_transfn(PG_FUNCTION_ARGS)
|
|||||||
MemoryContext aggcontext,
|
MemoryContext aggcontext,
|
||||||
oldcontext;
|
oldcontext;
|
||||||
StringInfo state;
|
StringInfo state;
|
||||||
Datum orig_val,
|
Datum val;
|
||||||
val;
|
|
||||||
TYPCATEGORY tcategory;
|
TYPCATEGORY tcategory;
|
||||||
Oid typoutput;
|
Oid typoutput;
|
||||||
bool typisvarlena;
|
bool typisvarlena;
|
||||||
@ -1692,13 +1660,12 @@ json_agg_transfn(PG_FUNCTION_ARGS)
|
|||||||
/* fast path for NULLs */
|
/* fast path for NULLs */
|
||||||
if (PG_ARGISNULL(1))
|
if (PG_ARGISNULL(1))
|
||||||
{
|
{
|
||||||
orig_val = (Datum) 0;
|
val = (Datum) 0;
|
||||||
datum_to_json(orig_val, true, state, 0, InvalidOid);
|
datum_to_json(val, true, state, 0, InvalidOid);
|
||||||
PG_RETURN_POINTER(state);
|
PG_RETURN_POINTER(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val = PG_GETARG_DATUM(1);
|
||||||
orig_val = PG_GETARG_DATUM(1);
|
|
||||||
|
|
||||||
getTypeOutputInfo(val_type, &typoutput, &typisvarlena);
|
getTypeOutputInfo(val_type, &typoutput, &typisvarlena);
|
||||||
|
|
||||||
@ -1732,15 +1699,6 @@ json_agg_transfn(PG_FUNCTION_ARGS)
|
|||||||
else
|
else
|
||||||
tcategory = TypeCategory(val_type);
|
tcategory = TypeCategory(val_type);
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have a toasted datum, forcibly detoast it here to avoid memory
|
|
||||||
* leakage inside the type's output routine.
|
|
||||||
*/
|
|
||||||
if (typisvarlena)
|
|
||||||
val = PointerGetDatum(PG_DETOAST_DATUM(orig_val));
|
|
||||||
else
|
|
||||||
val = orig_val;
|
|
||||||
|
|
||||||
if (!PG_ARGISNULL(0) &&
|
if (!PG_ARGISNULL(0) &&
|
||||||
(tcategory == TYPCATEGORY_ARRAY || tcategory == TYPCATEGORY_COMPOSITE))
|
(tcategory == TYPCATEGORY_ARRAY || tcategory == TYPCATEGORY_COMPOSITE))
|
||||||
{
|
{
|
||||||
@ -1749,10 +1707,6 @@ json_agg_transfn(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
datum_to_json(val, false, state, tcategory, typoutput);
|
datum_to_json(val, false, state, tcategory, typoutput);
|
||||||
|
|
||||||
/* Clean up detoasted copy, if any */
|
|
||||||
if (val != orig_val)
|
|
||||||
pfree(DatumGetPointer(val));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The transition type for array_agg() is declared to be "internal", which
|
* The transition type for array_agg() is declared to be "internal", which
|
||||||
* is a pass-by-value type the same size as a pointer. So we can safely
|
* is a pass-by-value type the same size as a pointer. So we can safely
|
||||||
|
Loading…
Reference in New Issue
Block a user