OSDN Git Service

Fix failure to account for memory used by tuplestore_putvalues().
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Jun 2011 18:05:22 +0000 (14:05 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Jun 2011 18:05:22 +0000 (14:05 -0400)
This oversight could result in a tuplestore using much more than the
intended amount of memory.  It would only happen in a code path that loaded
a tuplestore via tuplestore_putvalues(), and many of those won't emit huge
amounts of data; but cases such as holdable cursors and plpgsql's RETURN
NEXT command could have the problem.  The fix ensures that the tuplestore
will switch to write-to-disk mode when it overruns work_mem.

The potential overrun was finite, because we would still count the space
used by the tuple pointer array, so the tuplestore code would eventually
flip into write-to-disk mode anyway.  When storing wide tuples we would
go far past the expected work_mem usage before that happened; but this
may account for the lack of prior reports.

Back-patch to 8.4, where tuplestore_putvalues was introduced.

Per bug #6061 from Yann Delorme.

src/backend/utils/sort/tuplestore.c

index b59587b..4d6e3aa 100644 (file)
@@ -570,7 +570,8 @@ tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
        MemoryContext oldcxt = MemoryContextSwitchTo(state->context);
 
        /*
-        * Copy the tuple.      (Must do this even in WRITEFILE case.)
+        * Copy the tuple.  (Must do this even in WRITEFILE case.  Note that
+        * COPYTUP includes USEMEM, so we needn't do that here.)
         */
        tuple = COPYTUP(state, tuple);
 
@@ -580,9 +581,8 @@ tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
 }
 
 /*
- * Similar to tuplestore_puttuple(), but start from the values + nulls
- * array. This avoids requiring that the caller construct a HeapTuple,
- * saving a copy.
+ * Similar to tuplestore_puttuple(), but work from values + nulls arrays.
+ * This avoids an extra tuple-construction operation.
  */
 void
 tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
@@ -592,6 +592,7 @@ tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
        MemoryContext oldcxt = MemoryContextSwitchTo(state->context);
 
        tuple = heap_form_minimal_tuple(tdesc, values, isnull);
+       USEMEM(state, GetMemoryChunkSpace(tuple));
 
        tuplestore_puttuple_common(state, (void *) tuple);