@@ -288,11 +288,7 @@ struct Tuplesortstate
288288
289289/*
290290 * Function to write a stored tuple onto tape. The representation of the
291- * tuple on tape need not be the same as it is in memory; requirements on
292- * the tape representation are given below. Unless the slab allocator is
293- * used, after writing the tuple, pfree() the out-of-line data (not the
294- * SortTuple struct!), and increase state->availMem by the amount of
295- * memory space thereby released.
291+ * tuple on tape need not be the same as it is in memory.
296292 */
297293void (* writetup ) (Tuplesortstate * state ,LogicalTape * tape ,
298294SortTuple * stup );
@@ -549,7 +545,7 @@ struct Sharedsort
549545
550546#define REMOVEABBREV (state ,stup ,count )((*(state)->removeabbrev) (state, stup, count))
551547#define COMPARETUP (state ,a ,b )((*(state)->comparetup) (a, b, state))
552- #define WRITETUP (state ,tape ,stup )((*(state)->writetup) (state, tape, stup))
548+ #define WRITETUP (state ,tape ,stup )(writetuple (state, tape, stup))
553549#define READTUP (state ,stup ,tape ,len ) ((*(state)->readtup) (state, stup, tape, len))
554550#define LACKMEM (state )((state)->availMem < 0 && !(state)->slabAllocatorUsed)
555551#define USEMEM (state ,amt )((state)->availMem -= (amt))
@@ -618,6 +614,8 @@ static Tuplesortstate *tuplesort_begin_common(int workMem,
618614static void tuplesort_begin_batch (Tuplesortstate * state );
619615static void puttuple_common (Tuplesortstate * state ,SortTuple * tuple ,
620616bool useAbbrev );
617+ static void writetuple (Tuplesortstate * state ,LogicalTape * tape ,
618+ SortTuple * stup );
621619static bool consider_abort_common (Tuplesortstate * state );
622620static void inittapes (Tuplesortstate * state ,bool mergeruns );
623621static void inittapestate (Tuplesortstate * state ,int maxTapes );
@@ -1848,7 +1846,6 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
18481846/* copy the tuple into sort storage */
18491847tuple = ExecCopySlotMinimalTuple (slot );
18501848stup .tuple = (void * )tuple ;
1851- USEMEM (state ,GetMemoryChunkSpace (tuple ));
18521849/* set up first-column key value */
18531850htup .t_len = tuple -> t_len + MINIMAL_TUPLE_OFFSET ;
18541851htup .t_data = (HeapTupleHeader ) ((char * )tuple - MINIMAL_TUPLE_OFFSET );
@@ -1857,8 +1854,6 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
18571854state -> tupDesc ,
18581855& stup .isnull1 );
18591856
1860- MemoryContextSwitchTo (state -> sortcontext );
1861-
18621857puttuple_common (state ,& stup ,
18631858state -> sortKeys -> abbrev_converter && !stup .isnull1 );
18641859
@@ -1879,9 +1874,6 @@ tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
18791874/* copy the tuple into sort storage */
18801875tup = heap_copytuple (tup );
18811876stup .tuple = (void * )tup ;
1882- USEMEM (state ,GetMemoryChunkSpace (tup ));
1883-
1884- MemoryContextSwitchTo (state -> sortcontext );
18851877
18861878/*
18871879 * set up first-column key value, and potentially abbreviate, if it's a
@@ -1910,27 +1902,21 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
19101902ItemPointer self ,Datum * values ,
19111903bool * isnull )
19121904{
1913- MemoryContext oldcontext ;
19141905SortTuple stup ;
19151906IndexTuple tuple ;
19161907
19171908stup .tuple = index_form_tuple_context (RelationGetDescr (rel ),values ,
19181909isnull ,state -> tuplecontext );
19191910tuple = ((IndexTuple )stup .tuple );
19201911tuple -> t_tid = * self ;
1921- USEMEM (state ,GetMemoryChunkSpace (stup .tuple ));
19221912/* set up first-column key value */
19231913stup .datum1 = index_getattr (tuple ,
192419141 ,
19251915RelationGetDescr (state -> indexRel ),
19261916& stup .isnull1 );
19271917
1928- oldcontext = MemoryContextSwitchTo (state -> sortcontext );
1929-
19301918puttuple_common (state ,& stup ,
19311919state -> sortKeys && state -> sortKeys -> abbrev_converter && !stup .isnull1 );
1932-
1933- MemoryContextSwitchTo (oldcontext );
19341920}
19351921
19361922/*
@@ -1965,15 +1951,12 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
19651951stup .datum1 = !isNull ?val : (Datum )0 ;
19661952stup .isnull1 = isNull ;
19671953stup .tuple = NULL ;/* no separate storage */
1968- MemoryContextSwitchTo (state -> sortcontext );
19691954}
19701955else
19711956{
19721957stup .isnull1 = false;
19731958stup .datum1 = datumCopy (val , false,state -> datumTypeLen );
19741959stup .tuple = DatumGetPointer (stup .datum1 );
1975- USEMEM (state ,GetMemoryChunkSpace (stup .tuple ));
1976- MemoryContextSwitchTo (state -> sortcontext );
19771960}
19781961
19791962puttuple_common (state ,& stup ,
@@ -1988,8 +1971,14 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
19881971static void
19891972puttuple_common (Tuplesortstate * state ,SortTuple * tuple ,bool useAbbrev )
19901973{
1974+ MemoryContext oldcontext = MemoryContextSwitchTo (state -> sortcontext );
1975+
19911976Assert (!LEADER (state ));
19921977
1978+ /* Count the size of the out-of-line data */
1979+ if (tuple -> tuple != NULL )
1980+ USEMEM (state ,GetMemoryChunkSpace (tuple -> tuple ));
1981+
19931982if (!useAbbrev )
19941983{
19951984/*
@@ -2062,14 +2051,18 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple, bool useAbbrev)
20622051pg_rusage_show (& state -> ru_start ));
20632052#endif
20642053make_bounded_heap (state );
2054+ MemoryContextSwitchTo (oldcontext );
20652055return ;
20662056}
20672057
20682058/*
20692059 * Done if we still fit in available memory and have array slots.
20702060 */
20712061if (state -> memtupcount < state -> memtupsize && !LACKMEM (state ))
2062+ {
2063+ MemoryContextSwitchTo (oldcontext );
20722064return ;
2065+ }
20732066
20742067/*
20752068 * Nope; time to switch to tape-based operation.
@@ -2123,6 +2116,25 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple, bool useAbbrev)
21232116elog (ERROR ,"invalid tuplesort state" );
21242117break ;
21252118}
2119+ MemoryContextSwitchTo (oldcontext );
2120+ }
2121+
2122+ /*
2123+ * Write a stored tuple onto tape.tuple. Unless the slab allocator is
2124+ * used, after writing the tuple, pfree() the out-of-line data (not the
2125+ * SortTuple struct!), and increase state->availMem by the amount of
2126+ * memory space thereby released.
2127+ */
2128+ static void
2129+ writetuple (Tuplesortstate * state ,LogicalTape * tape ,SortTuple * stup )
2130+ {
2131+ state -> writetup (state ,tape ,stup );
2132+
2133+ if (!state -> slabAllocatorUsed && stup -> tuple )
2134+ {
2135+ FREEMEM (state ,GetMemoryChunkSpace (stup -> tuple ));
2136+ pfree (stup -> tuple );
2137+ }
21262138}
21272139
21282140static bool
@@ -3960,12 +3972,6 @@ writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
39603972if (state -> sortopt & TUPLESORT_RANDOMACCESS )/* need trailing length
39613973 * word? */
39623974LogicalTapeWrite (tape , (void * )& tuplen ,sizeof (tuplen ));
3963-
3964- if (!state -> slabAllocatorUsed )
3965- {
3966- FREEMEM (state ,GetMemoryChunkSpace (tuple ));
3967- heap_free_minimal_tuple (tuple );
3968- }
39693975}
39703976
39713977static void
@@ -4141,12 +4147,6 @@ writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
41414147if (state -> sortopt & TUPLESORT_RANDOMACCESS )/* need trailing length
41424148 * word? */
41434149LogicalTapeWrite (tape ,& tuplen ,sizeof (tuplen ));
4144-
4145- if (!state -> slabAllocatorUsed )
4146- {
4147- FREEMEM (state ,GetMemoryChunkSpace (tuple ));
4148- heap_freetuple (tuple );
4149- }
41504150}
41514151
41524152static void
@@ -4403,12 +4403,6 @@ writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
44034403if (state -> sortopt & TUPLESORT_RANDOMACCESS )/* need trailing length
44044404 * word? */
44054405LogicalTapeWrite (tape , (void * )& tuplen ,sizeof (tuplen ));
4406-
4407- if (!state -> slabAllocatorUsed )
4408- {
4409- FREEMEM (state ,GetMemoryChunkSpace (tuple ));
4410- pfree (tuple );
4411- }
44124406}
44134407
44144408static void
@@ -4495,12 +4489,6 @@ writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
44954489if (state -> sortopt & TUPLESORT_RANDOMACCESS )/* need trailing length
44964490 * word? */
44974491LogicalTapeWrite (tape , (void * )& writtenlen ,sizeof (writtenlen ));
4498-
4499- if (!state -> slabAllocatorUsed && stup -> tuple )
4500- {
4501- FREEMEM (state ,GetMemoryChunkSpace (stup -> tuple ));
4502- pfree (stup -> tuple );
4503- }
45044492}
45054493
45064494static void