diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 7cd678963a3bc6ff6df524867d45fceed6feb234..84aa271629bd39b533f6575831d2c7b78ce323f1 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.85 2001/03/23 04:49:53 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.86 2001/04/19 04:29:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -333,21 +333,32 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull) /* * If the attribute number is invalid, then we are supposed to return - * the entire tuple, we give back a whole slot so that callers know - * what the tuple looks like. XXX why copy? Couldn't we just give - * back the existing slot? + * the entire tuple; we give back a whole slot so that callers know + * what the tuple looks like. + * + * XXX this is a horrid crock: since the pointer to the slot might + * live longer than the current evaluation context, we are forced to + * copy the tuple and slot into a long-lived context --- we use + * TransactionCommandContext which should be safe enough. This + * represents a serious memory leak if many such tuples are processed + * in one command, however. We ought to redesign the representation + * of whole-tuple datums so that this is not necessary. + * + * We assume it's OK to point to the existing tupleDescriptor, rather + * than copy that too. */ if (attnum == InvalidAttrNumber) { - TupleTableSlot *tempSlot = MakeTupleTableSlot(); - TupleDesc td; + MemoryContext oldContext; + TupleTableSlot *tempSlot; HeapTuple tup; + oldContext = MemoryContextSwitchTo(TransactionCommandContext); + tempSlot = MakeTupleTableSlot(); tup = heap_copytuple(heapTuple); - td = CreateTupleDescCopy(tuple_type); - - ExecSetSlotDescriptor(tempSlot, td, true); ExecStoreTuple(tup, tempSlot, InvalidBuffer, true); + ExecSetSlotDescriptor(tempSlot, tuple_type, false); + MemoryContextSwitchTo(oldContext); return PointerGetDatum(tempSlot); }