postgres.git / summary / log / commit / refs

commit    8520174b4e788736a41797320d9d36a4372b56df
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Wed Jun 15 18:05:22 2011 +0000
First released in: 9.2.0, 8.4.9, 9.0.5, 9.1.0

    Fix failure to account for memory used by tuplestore_putvalues().
    
    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 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index 4cfc38ef8b5..5d34a670be3 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -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); [parent: 212567ad3ee2]