OSDN Git Service

Kluge solution for Alex Pilosov's report of problems with whole-tuple
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 19 Apr 2001 04:29:02 +0000 (04:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 19 Apr 2001 04:29:02 +0000 (04:29 +0000)
function arguments in join queries: copy the tuples into
TransactionCommandContext so they don't get recycled too soon.  This is
horrid, but not any worse than 7.0 or before, which also leaked such
tuples until end of query.  A proper fix will require allowing tuple
datums to be physically stored inside larger tuple datums, which opens
up a bunch of issues that can't realistically be solved for 7.1.1.

src/backend/executor/execQual.c

index 7cd6789..84aa271 100644 (file)
@@ -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);
        }