aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/json.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-11-03 11:55:37 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2013-11-03 11:55:37 -0500
commite36ce0c7f7b329b25f92cf440fd88fcc695de101 (patch)
tree078fd539213c674370ca4f5006c338ae30e015de /src/backend/utils/adt/json.c
parentb006f4ddb988568081f8290fac77f9402b137120 (diff)
downloadpostgresql-e36ce0c7f7b329b25f92cf440fd88fcc695de101.tar.gz
postgresql-e36ce0c7f7b329b25f92cf440fd88fcc695de101.zip
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.
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r--src/backend/utils/adt/json.c60
1 files changed, 7 insertions, 53 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index b6199fbf68d..7685410f185 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