On Wed, Jul 11, 2018 at 03:27:13PM +0900, Michael Paquier wrote: > I don't think that your solution is correct. From my read of 37a795a6, > the tuple descriptor is moved from the query-lifespan memory context > (ecxt_per_query_memory) to a function-level context, which could cause > the descriptor to become busted as your test is pointing out. Tom?
Hacking my way out I am finishing with the attached, which fixes the problem and passes all regression tests. I am not completely sure that this the right approach though, I would need to think a bit more about it. -- Michael
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index e358b5ad13..b82060528b 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -2721,24 +2721,22 @@ JsValueToJsObject(JsValue *jsv, JsObject *jso)
static void
update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
{
- if (!io->tupdesc ||
- io->tupdesc->tdtypeid != io->base_typid ||
- io->tupdesc->tdtypmod != io->base_typmod)
- {
- TupleDesc tupdesc = lookup_rowtype_tupdesc(io->base_typid,
- io->base_typmod);
- MemoryContext oldcxt;
+ TupleDesc tupdesc;
+ MemoryContext oldcxt;
- if (io->tupdesc)
- FreeTupleDesc(io->tupdesc);
+ if (io->tupdesc != NULL &&
+ io->tupdesc->tdtypeid == io->base_typid &&
+ io->tupdesc->tdtypmod == io->base_typmod)
+ return;
- /* copy tuple desc without constraints into cache memory context */
- oldcxt = MemoryContextSwitchTo(mcxt);
- io->tupdesc = CreateTupleDescCopy(tupdesc);
- MemoryContextSwitchTo(oldcxt);
+ tupdesc = lookup_rowtype_tupdesc(io->base_typid, io->base_typmod);
- ReleaseTupleDesc(tupdesc);
- }
+ /* copy tuple desc without constraints into cache memory context */
+ oldcxt = MemoryContextSwitchTo(mcxt);
+ io->tupdesc = CreateTupleDescCopy(tupdesc);
+ MemoryContextSwitchTo(oldcxt);
+
+ ReleaseTupleDesc(tupdesc);
}
/* recursively populate a composite (row type) value from json/jsonb */
@@ -3577,8 +3575,8 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
if (!cache)
{
fcinfo->flinfo->fn_extra = cache =
- MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
- cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
+ MemoryContextAllocZero(rsi->econtext->ecxt_per_query_memory, sizeof(*cache));
+ cache->fn_mcxt = rsi->econtext->ecxt_per_query_memory;
if (have_record_arg)
{
signature.asc
Description: PGP signature
