|
|
|
|
@ -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 |
|
|
|
|
|