From e36ce0c7f7b329b25f92cf440fd88fcc695de101 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 3 Nov 2013 11:55:37 -0500 Subject: [PATCH] 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. --- src/backend/utils/adt/json.c | 60 +++++------------------------------- 1 file changed, 7 insertions(+), 53 deletions(-) diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index b6199fbf68..7685410f18 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -1425,8 +1425,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds) for (i = 0; i < tupdesc->natts; i++) { - Datum val, - origval; + Datum val; bool isnull; char *attname; TYPCATEGORY tcategory; @@ -1445,7 +1444,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds) escape_json(result, attname); appendStringInfoChar(result, ':'); - origval = heap_getattr(tuple, i + 1, tupdesc, &isnull); + val = heap_getattr(tuple, i + 1, tupdesc, &isnull); getTypeOutputInfo(tupdesc->attrs[i]->atttypid, &typoutput, &typisvarlena); @@ -1480,20 +1479,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds) else 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); - - /* Clean up detoasted copy, if any */ - if (val != origval) - pfree(DatumGetPointer(val)); } appendStringInfoChar(result, '}'); @@ -1572,10 +1558,9 @@ row_to_json_pretty(PG_FUNCTION_ARGS) Datum to_json(PG_FUNCTION_ARGS) { + Datum val = PG_GETARG_DATUM(0); Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0); StringInfo result; - Datum orig_val, - val; TYPCATEGORY tcategory; Oid typoutput; bool typisvarlena; @@ -1586,11 +1571,8 @@ to_json(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data type"))); - result = makeStringInfo(); - orig_val = PG_ARGISNULL(0) ? (Datum) 0 : PG_GETARG_DATUM(0); - getTypeOutputInfo(val_type, &typoutput, &typisvarlena); if (val_type > FirstNormalObjectId) @@ -1623,21 +1605,8 @@ to_json(PG_FUNCTION_ARGS) else 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); - /* Clean up detoasted copy, if any */ - if (val != orig_val) - pfree(DatumGetPointer(val)); - PG_RETURN_TEXT_P(cstring_to_text(result->data)); } @@ -1651,8 +1620,7 @@ json_agg_transfn(PG_FUNCTION_ARGS) MemoryContext aggcontext, oldcontext; StringInfo state; - Datum orig_val, - val; + Datum val; TYPCATEGORY tcategory; Oid typoutput; bool typisvarlena; @@ -1692,13 +1660,12 @@ json_agg_transfn(PG_FUNCTION_ARGS) /* fast path for NULLs */ if (PG_ARGISNULL(1)) { - orig_val = (Datum) 0; - datum_to_json(orig_val, true, state, 0, InvalidOid); + val = (Datum) 0; + datum_to_json(val, true, state, 0, InvalidOid); PG_RETURN_POINTER(state); } - - orig_val = PG_GETARG_DATUM(1); + val = PG_GETARG_DATUM(1); getTypeOutputInfo(val_type, &typoutput, &typisvarlena); @@ -1732,15 +1699,6 @@ json_agg_transfn(PG_FUNCTION_ARGS) else 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) && (tcategory == TYPCATEGORY_ARRAY || tcategory == TYPCATEGORY_COMPOSITE)) { @@ -1749,10 +1707,6 @@ json_agg_transfn(PG_FUNCTION_ARGS) 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 * is a pass-by-value type the same size as a pointer. So we can safely