Header And Logo

PostgreSQL
| The world's most advanced open source database.

Typedefs | Functions

tuplesort.h File Reference

#include "access/itup.h"
#include "executor/tuptable.h"
#include "fmgr.h"
#include "utils/relcache.h"
Include dependency graph for tuplesort.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct Tuplesortstate Tuplesortstate

Functions

Tuplesortstatetuplesort_begin_heap (TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, bool randomAccess)
Tuplesortstatetuplesort_begin_cluster (TupleDesc tupDesc, Relation indexRel, int workMem, bool randomAccess)
Tuplesortstatetuplesort_begin_index_btree (Relation heapRel, Relation indexRel, bool enforceUnique, int workMem, bool randomAccess)
Tuplesortstatetuplesort_begin_index_hash (Relation heapRel, Relation indexRel, uint32 hash_mask, int workMem, bool randomAccess)
Tuplesortstatetuplesort_begin_datum (Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, bool randomAccess)
void tuplesort_set_bound (Tuplesortstate *state, int64 bound)
void tuplesort_puttupleslot (Tuplesortstate *state, TupleTableSlot *slot)
void tuplesort_putheaptuple (Tuplesortstate *state, HeapTuple tup)
void tuplesort_putindextuple (Tuplesortstate *state, IndexTuple tuple)
void tuplesort_putdatum (Tuplesortstate *state, Datum val, bool isNull)
void tuplesort_performsort (Tuplesortstate *state)
bool tuplesort_gettupleslot (Tuplesortstate *state, bool forward, TupleTableSlot *slot)
HeapTuple tuplesort_getheaptuple (Tuplesortstate *state, bool forward, bool *should_free)
IndexTuple tuplesort_getindextuple (Tuplesortstate *state, bool forward, bool *should_free)
bool tuplesort_getdatum (Tuplesortstate *state, bool forward, Datum *val, bool *isNull)
void tuplesort_end (Tuplesortstate *state)
void tuplesort_get_stats (Tuplesortstate *state, const char **sortMethod, const char **spaceType, long *spaceUsed)
int tuplesort_merge_order (long allowedMem)
void tuplesort_rescan (Tuplesortstate *state)
void tuplesort_markpos (Tuplesortstate *state)
void tuplesort_restorepos (Tuplesortstate *state)

Typedef Documentation

Definition at line 32 of file tuplesort.h.


Function Documentation

Tuplesortstate* tuplesort_begin_cluster ( TupleDesc  tupDesc,
Relation  indexRel,
int  workMem,
bool  randomAccess 
)

Definition at line 663 of file tuplesort.c.

References _bt_mkscankey_nodata(), Assert, BTREE_AM_OID, BuildIndexInfo(), CLUSTER_SORT, Tuplesortstate::comparetup, Tuplesortstate::copytup, CreateExecutorState(), ExprContext::ecxt_scantuple, elog, Tuplesortstate::estate, GetPerTupleExprContext, IndexInfo::ii_Expressions, Tuplesortstate::indexInfo, Tuplesortstate::indexScanKey, LOG, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), Tuplesortstate::nKeys, NULL, RelationData::rd_rel, Tuplesortstate::readtup, RelationGetNumberOfAttributes, Tuplesortstate::reversedirection, Tuplesortstate::sortcontext, Tuplesortstate::tupDesc, tuplesort_begin_common(), and Tuplesortstate::writetup.

Referenced by copy_heap_data().

{
    Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
    MemoryContext oldcontext;

    Assert(indexRel->rd_rel->relam == BTREE_AM_OID);

    oldcontext = MemoryContextSwitchTo(state->sortcontext);

#ifdef TRACE_SORT
    if (trace_sort)
        elog(LOG,
             "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c",
             RelationGetNumberOfAttributes(indexRel),
             workMem, randomAccess ? 't' : 'f');
#endif

    state->nKeys = RelationGetNumberOfAttributes(indexRel);

    TRACE_POSTGRESQL_SORT_START(CLUSTER_SORT,
                                false,  /* no unique check */
                                state->nKeys,
                                workMem,
                                randomAccess);

    state->comparetup = comparetup_cluster;
    state->copytup = copytup_cluster;
    state->writetup = writetup_cluster;
    state->readtup = readtup_cluster;
    state->reversedirection = reversedirection_index_btree;

    state->indexInfo = BuildIndexInfo(indexRel);
    state->indexScanKey = _bt_mkscankey_nodata(indexRel);

    state->tupDesc = tupDesc;   /* assume we need not copy tupDesc */

    if (state->indexInfo->ii_Expressions != NULL)
    {
        TupleTableSlot *slot;
        ExprContext *econtext;

        /*
         * We will need to use FormIndexDatum to evaluate the index
         * expressions.  To do that, we need an EState, as well as a
         * TupleTableSlot to put the table tuples into.  The econtext's
         * scantuple has to point to that slot, too.
         */
        state->estate = CreateExecutorState();
        slot = MakeSingleTupleTableSlot(tupDesc);
        econtext = GetPerTupleExprContext(state->estate);
        econtext->ecxt_scantuple = slot;
    }

    MemoryContextSwitchTo(oldcontext);

    return state;
}

Tuplesortstate* tuplesort_begin_datum ( Oid  datumType,
Oid  sortOperator,
Oid  sortCollation,
bool  nullsFirstFlag,
int  workMem,
bool  randomAccess 
)

Definition at line 804 of file tuplesort.c.

References Tuplesortstate::comparetup, Tuplesortstate::copytup, CurrentMemoryContext, DATUM_SORT, Tuplesortstate::datumType, Tuplesortstate::datumTypeByVal, Tuplesortstate::datumTypeLen, elog, get_typlenbyval(), LOG, MemoryContextSwitchTo(), Tuplesortstate::nKeys, Tuplesortstate::onlyKey, palloc0(), PrepareSortSupportFromOrderingOp(), Tuplesortstate::readtup, Tuplesortstate::reversedirection, Tuplesortstate::sortcontext, SortSupportData::ssup_collation, SortSupportData::ssup_cxt, SortSupportData::ssup_nulls_first, tuplesort_begin_common(), and Tuplesortstate::writetup.

Referenced by initialize_aggregates(), and validate_index().

{
    Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
    MemoryContext oldcontext;
    int16       typlen;
    bool        typbyval;

    oldcontext = MemoryContextSwitchTo(state->sortcontext);

#ifdef TRACE_SORT
    if (trace_sort)
        elog(LOG,
             "begin datum sort: workMem = %d, randomAccess = %c",
             workMem, randomAccess ? 't' : 'f');
#endif

    state->nKeys = 1;           /* always a one-column sort */

    TRACE_POSTGRESQL_SORT_START(DATUM_SORT,
                                false,  /* no unique check */
                                1,
                                workMem,
                                randomAccess);

    state->comparetup = comparetup_datum;
    state->copytup = copytup_datum;
    state->writetup = writetup_datum;
    state->readtup = readtup_datum;
    state->reversedirection = reversedirection_datum;

    state->datumType = datumType;

    /* Prepare SortSupport data */
    state->onlyKey = (SortSupport) palloc0(sizeof(SortSupportData));

    state->onlyKey->ssup_cxt = CurrentMemoryContext;
    state->onlyKey->ssup_collation = sortCollation;
    state->onlyKey->ssup_nulls_first = nullsFirstFlag;

    PrepareSortSupportFromOrderingOp(sortOperator, state->onlyKey);

    /* lookup necessary attributes of the datum type */
    get_typlenbyval(datumType, &typlen, &typbyval);
    state->datumTypeLen = typlen;
    state->datumTypeByVal = typbyval;

    MemoryContextSwitchTo(oldcontext);

    return state;
}

Tuplesortstate* tuplesort_begin_heap ( TupleDesc  tupDesc,
int  nkeys,
AttrNumber attNums,
Oid sortOperators,
Oid sortCollations,
bool nullsFirstFlags,
int  workMem,
bool  randomAccess 
)

Definition at line 599 of file tuplesort.c.

References AssertArg, Tuplesortstate::comparetup, Tuplesortstate::copytup, CurrentMemoryContext, elog, HEAP_SORT, i, LOG, MemoryContextSwitchTo(), Tuplesortstate::nKeys, Tuplesortstate::onlyKey, palloc0(), PrepareSortSupportFromOrderingOp(), Tuplesortstate::readtup, Tuplesortstate::reversedirection, Tuplesortstate::sortcontext, Tuplesortstate::sortKeys, SortSupportData::ssup_attno, SortSupportData::ssup_collation, SortSupportData::ssup_cxt, SortSupportData::ssup_nulls_first, Tuplesortstate::tupDesc, tuplesort_begin_common(), and Tuplesortstate::writetup.

Referenced by ExecSort(), and initialize_aggregates().

{
    Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
    MemoryContext oldcontext;
    int         i;

    oldcontext = MemoryContextSwitchTo(state->sortcontext);

    AssertArg(nkeys > 0);

#ifdef TRACE_SORT
    if (trace_sort)
        elog(LOG,
             "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c",
             nkeys, workMem, randomAccess ? 't' : 'f');
#endif

    state->nKeys = nkeys;

    TRACE_POSTGRESQL_SORT_START(HEAP_SORT,
                                false,  /* no unique check */
                                nkeys,
                                workMem,
                                randomAccess);

    state->comparetup = comparetup_heap;
    state->copytup = copytup_heap;
    state->writetup = writetup_heap;
    state->readtup = readtup_heap;
    state->reversedirection = reversedirection_heap;

    state->tupDesc = tupDesc;   /* assume we need not copy tupDesc */

    /* Prepare SortSupport data for each column */
    state->sortKeys = (SortSupport) palloc0(nkeys * sizeof(SortSupportData));

    for (i = 0; i < nkeys; i++)
    {
        SortSupport sortKey = state->sortKeys + i;

        AssertArg(attNums[i] != 0);
        AssertArg(sortOperators[i] != 0);

        sortKey->ssup_cxt = CurrentMemoryContext;
        sortKey->ssup_collation = sortCollations[i];
        sortKey->ssup_nulls_first = nullsFirstFlags[i];
        sortKey->ssup_attno = attNums[i];

        PrepareSortSupportFromOrderingOp(sortOperators[i], sortKey);
    }

    if (nkeys == 1)
        state->onlyKey = state->sortKeys;

    MemoryContextSwitchTo(oldcontext);

    return state;
}

Tuplesortstate* tuplesort_begin_index_btree ( Relation  heapRel,
Relation  indexRel,
bool  enforceUnique,
int  workMem,
bool  randomAccess 
)

Definition at line 724 of file tuplesort.c.

References _bt_mkscankey_nodata(), Tuplesortstate::comparetup, Tuplesortstate::copytup, elog, Tuplesortstate::enforceUnique, Tuplesortstate::heapRel, INDEX_SORT, Tuplesortstate::indexRel, Tuplesortstate::indexScanKey, LOG, MemoryContextSwitchTo(), Tuplesortstate::nKeys, Tuplesortstate::readtup, RelationGetNumberOfAttributes, Tuplesortstate::reversedirection, Tuplesortstate::sortcontext, tuplesort_begin_common(), and Tuplesortstate::writetup.

Referenced by _bt_spoolinit().

{
    Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
    MemoryContext oldcontext;

    oldcontext = MemoryContextSwitchTo(state->sortcontext);

#ifdef TRACE_SORT
    if (trace_sort)
        elog(LOG,
             "begin index sort: unique = %c, workMem = %d, randomAccess = %c",
             enforceUnique ? 't' : 'f',
             workMem, randomAccess ? 't' : 'f');
#endif

    state->nKeys = RelationGetNumberOfAttributes(indexRel);

    TRACE_POSTGRESQL_SORT_START(INDEX_SORT,
                                enforceUnique,
                                state->nKeys,
                                workMem,
                                randomAccess);

    state->comparetup = comparetup_index_btree;
    state->copytup = copytup_index;
    state->writetup = writetup_index;
    state->readtup = readtup_index;
    state->reversedirection = reversedirection_index_btree;

    state->heapRel = heapRel;
    state->indexRel = indexRel;
    state->indexScanKey = _bt_mkscankey_nodata(indexRel);
    state->enforceUnique = enforceUnique;

    MemoryContextSwitchTo(oldcontext);

    return state;
}

Tuplesortstate* tuplesort_begin_index_hash ( Relation  heapRel,
Relation  indexRel,
uint32  hash_mask,
int  workMem,
bool  randomAccess 
)

Definition at line 767 of file tuplesort.c.

References Tuplesortstate::comparetup, Tuplesortstate::copytup, elog, Tuplesortstate::hash_mask, Tuplesortstate::heapRel, Tuplesortstate::indexRel, LOG, MemoryContextSwitchTo(), Tuplesortstate::nKeys, Tuplesortstate::readtup, Tuplesortstate::reversedirection, Tuplesortstate::sortcontext, tuplesort_begin_common(), and Tuplesortstate::writetup.

Referenced by _h_spoolinit().

{
    Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
    MemoryContext oldcontext;

    oldcontext = MemoryContextSwitchTo(state->sortcontext);

#ifdef TRACE_SORT
    if (trace_sort)
        elog(LOG,
        "begin index sort: hash_mask = 0x%x, workMem = %d, randomAccess = %c",
             hash_mask,
             workMem, randomAccess ? 't' : 'f');
#endif

    state->nKeys = 1;           /* Only one sort column, the hash code */

    state->comparetup = comparetup_index_hash;
    state->copytup = copytup_index;
    state->writetup = writetup_index;
    state->readtup = readtup_index;
    state->reversedirection = reversedirection_index_hash;

    state->heapRel = heapRel;
    state->indexRel = indexRel;

    state->hash_mask = hash_mask;

    MemoryContextSwitchTo(oldcontext);

    return state;
}

void tuplesort_end ( Tuplesortstate state  ) 

Definition at line 901 of file tuplesort.c.

References Tuplesortstate::allowedMem, Tuplesortstate::availMem, ExprContext::ecxt_scantuple, elog, Tuplesortstate::estate, ExecDropSingleTupleTableSlot(), FreeExecutorState(), GetPerTupleExprContext, LOG, LogicalTapeSetBlocks(), LogicalTapeSetClose(), MemoryContextDelete(), MemoryContextSwitchTo(), NULL, pg_rusage_show(), Tuplesortstate::sortcontext, and Tuplesortstate::tapeset.

Referenced by _bt_spooldestroy(), _h_spooldestroy(), copy_heap_data(), ExecEndAgg(), ExecEndSort(), ExecReScanAgg(), ExecReScanSort(), initialize_aggregates(), process_ordered_aggregate_multi(), process_ordered_aggregate_single(), and validate_index().

{
    /* context swap probably not needed, but let's be safe */
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);

#ifdef TRACE_SORT
    long        spaceUsed;

    if (state->tapeset)
        spaceUsed = LogicalTapeSetBlocks(state->tapeset);
    else
        spaceUsed = (state->allowedMem - state->availMem + 1023) / 1024;
#endif

    /*
     * Delete temporary "tape" files, if any.
     *
     * Note: want to include this in reported total cost of sort, hence need
     * for two #ifdef TRACE_SORT sections.
     */
    if (state->tapeset)
        LogicalTapeSetClose(state->tapeset);

#ifdef TRACE_SORT
    if (trace_sort)
    {
        if (state->tapeset)
            elog(LOG, "external sort ended, %ld disk blocks used: %s",
                 spaceUsed, pg_rusage_show(&state->ru_start));
        else
            elog(LOG, "internal sort ended, %ld KB used: %s",
                 spaceUsed, pg_rusage_show(&state->ru_start));
    }

    TRACE_POSTGRESQL_SORT_DONE(state->tapeset != NULL, spaceUsed);
#else

    /*
     * If you disabled TRACE_SORT, you can still probe sort__done, but you
     * ain't getting space-used stats.
     */
    TRACE_POSTGRESQL_SORT_DONE(state->tapeset != NULL, 0L);
#endif

    /* Free any execution state created for CLUSTER case */
    if (state->estate != NULL)
    {
        ExprContext *econtext = GetPerTupleExprContext(state->estate);

        ExecDropSingleTupleTableSlot(econtext->ecxt_scantuple);
        FreeExecutorState(state->estate);
    }

    MemoryContextSwitchTo(oldcontext);

    /*
     * Free the per-sort memory context, thereby releasing all working memory,
     * including the Tuplesortstate struct itself.
     */
    MemoryContextDelete(state->sortcontext);
}

void tuplesort_get_stats ( Tuplesortstate state,
const char **  sortMethod,
const char **  spaceType,
long *  spaceUsed 
)

Definition at line 2437 of file tuplesort.c.

References Tuplesortstate::allowedMem, Tuplesortstate::availMem, Tuplesortstate::boundUsed, LogicalTapeSetBlocks(), Tuplesortstate::status, Tuplesortstate::tapeset, TSS_FINALMERGE, TSS_SORTEDINMEM, and TSS_SORTEDONTAPE.

Referenced by show_sort_info().

{
    /*
     * Note: it might seem we should provide both memory and disk usage for a
     * disk-based sort.  However, the current code doesn't track memory space
     * accurately once we have begun to return tuples to the caller (since we
     * don't account for pfree's the caller is expected to do), so we cannot
     * rely on availMem in a disk sort.  This does not seem worth the overhead
     * to fix.  Is it worth creating an API for the memory context code to
     * tell us how much is actually used in sortcontext?
     */
    if (state->tapeset)
    {
        *spaceType = "Disk";
        *spaceUsed = LogicalTapeSetBlocks(state->tapeset) * (BLCKSZ / 1024);
    }
    else
    {
        *spaceType = "Memory";
        *spaceUsed = (state->allowedMem - state->availMem + 1023) / 1024;
    }

    switch (state->status)
    {
        case TSS_SORTEDINMEM:
            if (state->boundUsed)
                *sortMethod = "top-N heapsort";
            else
                *sortMethod = "quicksort";
            break;
        case TSS_SORTEDONTAPE:
            *sortMethod = "external sort";
            break;
        case TSS_FINALMERGE:
            *sortMethod = "external merge";
            break;
        default:
            *sortMethod = "still in progress";
            break;
    }
}

bool tuplesort_getdatum ( Tuplesortstate state,
bool  forward,
Datum val,
bool isNull 
)

Definition at line 1679 of file tuplesort.c.

References SortTuple::datum1, datumCopy(), Tuplesortstate::datumTypeByVal, Tuplesortstate::datumTypeLen, SortTuple::isnull1, MemoryContextSwitchTo(), Tuplesortstate::sortcontext, and tuplesort_gettuple_common().

Referenced by process_ordered_aggregate_single(), and validate_index_heapscan().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;
    bool        should_free;

    if (!tuplesort_gettuple_common(state, forward, &stup, &should_free))
    {
        MemoryContextSwitchTo(oldcontext);
        return false;
    }

    if (stup.isnull1 || state->datumTypeByVal)
    {
        *val = stup.datum1;
        *isNull = stup.isnull1;
    }
    else
    {
        if (should_free)
            *val = stup.datum1;
        else
            *val = datumCopy(stup.datum1, false, state->datumTypeLen);
        *isNull = false;
    }

    MemoryContextSwitchTo(oldcontext);

    return true;
}

HeapTuple tuplesort_getheaptuple ( Tuplesortstate state,
bool  forward,
bool should_free 
)

Definition at line 1638 of file tuplesort.c.

References MemoryContextSwitchTo(), Tuplesortstate::sortcontext, SortTuple::tuple, and tuplesort_gettuple_common().

Referenced by copy_heap_data().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;

    if (!tuplesort_gettuple_common(state, forward, &stup, should_free))
        stup.tuple = NULL;

    MemoryContextSwitchTo(oldcontext);

    return stup.tuple;
}

IndexTuple tuplesort_getindextuple ( Tuplesortstate state,
bool  forward,
bool should_free 
)

Definition at line 1657 of file tuplesort.c.

References MemoryContextSwitchTo(), Tuplesortstate::sortcontext, SortTuple::tuple, and tuplesort_gettuple_common().

Referenced by _bt_load(), and _h_indexbuild().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;

    if (!tuplesort_gettuple_common(state, forward, &stup, should_free))
        stup.tuple = NULL;

    MemoryContextSwitchTo(oldcontext);

    return (IndexTuple) stup.tuple;
}

bool tuplesort_gettupleslot ( Tuplesortstate state,
bool  forward,
TupleTableSlot slot 
)

Definition at line 1608 of file tuplesort.c.

References ExecClearTuple(), ExecStoreMinimalTuple(), MemoryContextSwitchTo(), Tuplesortstate::sortcontext, SortTuple::tuple, and tuplesort_gettuple_common().

Referenced by ExecSort(), and process_ordered_aggregate_multi().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;
    bool        should_free;

    if (!tuplesort_gettuple_common(state, forward, &stup, &should_free))
        stup.tuple = NULL;

    MemoryContextSwitchTo(oldcontext);

    if (stup.tuple)
    {
        ExecStoreMinimalTuple((MinimalTuple) stup.tuple, slot, should_free);
        return true;
    }
    else
    {
        ExecClearTuple(slot);
        return false;
    }
}

void tuplesort_markpos ( Tuplesortstate state  ) 
int tuplesort_merge_order ( long  allowedMem  ) 

Definition at line 1718 of file tuplesort.c.

References Max, MERGE_BUFFER_SIZE, MINORDER, and TAPE_BUFFER_OVERHEAD.

Referenced by cost_sort(), and inittapes().

{
    int         mOrder;

    /*
     * We need one tape for each merge input, plus another one for the output,
     * and each of these tapes needs buffer space.  In addition we want
     * MERGE_BUFFER_SIZE workspace per input tape (but the output tape doesn't
     * count).
     *
     * Note: you might be thinking we need to account for the memtuples[]
     * array in this calculation, but we effectively treat that as part of the
     * MERGE_BUFFER_SIZE workspace.
     */
    mOrder = (allowedMem - TAPE_BUFFER_OVERHEAD) /
        (MERGE_BUFFER_SIZE + TAPE_BUFFER_OVERHEAD);

    /* Even in minimum memory, use at least a MINORDER merge */
    mOrder = Max(mOrder, MINORDER);

    return mOrder;
}

void tuplesort_performsort ( Tuplesortstate state  ) 

Definition at line 1312 of file tuplesort.c.

References Tuplesortstate::activeTapes, Tuplesortstate::comparetup, Tuplesortstate::current, dumptuples(), elog, Tuplesortstate::eof_reached, ERROR, LOG, Tuplesortstate::markpos_block, Tuplesortstate::markpos_eof, Tuplesortstate::markpos_offset, MemoryContextSwitchTo(), Tuplesortstate::memtupcount, Tuplesortstate::memtuples, mergeruns(), NULL, Tuplesortstate::onlyKey, pg_rusage_show(), sort_bounded_heap(), Tuplesortstate::sortcontext, Tuplesortstate::status, TSS_BOUNDED, TSS_BUILDRUNS, TSS_FINALMERGE, and TSS_INITIAL.

Referenced by _bt_leafbuild(), _h_indexbuild(), copy_heap_data(), ExecSort(), process_ordered_aggregate_multi(), process_ordered_aggregate_single(), and validate_index().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);

#ifdef TRACE_SORT
    if (trace_sort)
        elog(LOG, "performsort starting: %s",
             pg_rusage_show(&state->ru_start));
#endif

    switch (state->status)
    {
        case TSS_INITIAL:

            /*
             * We were able to accumulate all the tuples within the allowed
             * amount of memory.  Just qsort 'em and we're done.
             */
            if (state->memtupcount > 1)
            {
                /* Can we use the single-key sort function? */
                if (state->onlyKey != NULL)
                    qsort_ssup(state->memtuples, state->memtupcount,
                               state->onlyKey);
                else
                    qsort_tuple(state->memtuples,
                                state->memtupcount,
                                state->comparetup,
                                state);
            }
            state->current = 0;
            state->eof_reached = false;
            state->markpos_offset = 0;
            state->markpos_eof = false;
            state->status = TSS_SORTEDINMEM;
            break;

        case TSS_BOUNDED:

            /*
             * We were able to accumulate all the tuples required for output
             * in memory, using a heap to eliminate excess tuples.  Now we
             * have to transform the heap to a properly-sorted array.
             */
            sort_bounded_heap(state);
            state->current = 0;
            state->eof_reached = false;
            state->markpos_offset = 0;
            state->markpos_eof = false;
            state->status = TSS_SORTEDINMEM;
            break;

        case TSS_BUILDRUNS:

            /*
             * Finish tape-based sort.  First, flush all tuples remaining in
             * memory out to tape; then merge until we have a single remaining
             * run (or, if !randomAccess, one run per tape). Note that
             * mergeruns sets the correct state->status.
             */
            dumptuples(state, true);
            mergeruns(state);
            state->eof_reached = false;
            state->markpos_block = 0L;
            state->markpos_offset = 0;
            state->markpos_eof = false;
            break;

        default:
            elog(ERROR, "invalid tuplesort state");
            break;
    }

#ifdef TRACE_SORT
    if (trace_sort)
    {
        if (state->status == TSS_FINALMERGE)
            elog(LOG, "performsort done (except %d-way final merge): %s",
                 state->activeTapes,
                 pg_rusage_show(&state->ru_start));
        else
            elog(LOG, "performsort done: %s",
                 pg_rusage_show(&state->ru_start));
    }
#endif

    MemoryContextSwitchTo(oldcontext);
}

void tuplesort_putdatum ( Tuplesortstate state,
Datum  val,
bool  isNull 
)

Definition at line 1155 of file tuplesort.c.

References SortTuple::datum1, datumCopy(), DatumGetPointer, Tuplesortstate::datumTypeByVal, Tuplesortstate::datumTypeLen, GetMemoryChunkSpace(), SortTuple::isnull1, MemoryContextSwitchTo(), puttuple_common(), Tuplesortstate::sortcontext, SortTuple::tuple, and USEMEM.

Referenced by advance_aggregates(), and validate_index_callback().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;

    /*
     * If it's a pass-by-reference value, copy it into memory we control, and
     * decrease availMem.  Then call the common code.
     */
    if (isNull || state->datumTypeByVal)
    {
        stup.datum1 = val;
        stup.isnull1 = isNull;
        stup.tuple = NULL;      /* no separate storage */
    }
    else
    {
        stup.datum1 = datumCopy(val, false, state->datumTypeLen);
        stup.isnull1 = false;
        stup.tuple = DatumGetPointer(stup.datum1);
        USEMEM(state, GetMemoryChunkSpace(stup.tuple));
    }

    puttuple_common(state, &stup);

    MemoryContextSwitchTo(oldcontext);
}

void tuplesort_putheaptuple ( Tuplesortstate state,
HeapTuple  tup 
)

Definition at line 1111 of file tuplesort.c.

References COPYTUP, MemoryContextSwitchTo(), puttuple_common(), and Tuplesortstate::sortcontext.

Referenced by copy_heap_data().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;

    /*
     * Copy the given tuple into memory we control, and decrease availMem.
     * Then call the common code.
     */
    COPYTUP(state, &stup, (void *) tup);

    puttuple_common(state, &stup);

    MemoryContextSwitchTo(oldcontext);
}

void tuplesort_putindextuple ( Tuplesortstate state,
IndexTuple  tuple 
)

Definition at line 1133 of file tuplesort.c.

References COPYTUP, MemoryContextSwitchTo(), puttuple_common(), and Tuplesortstate::sortcontext.

Referenced by _bt_spool(), and _h_spool().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;

    /*
     * Copy the given tuple into memory we control, and decrease availMem.
     * Then call the common code.
     */
    COPYTUP(state, &stup, (void *) tuple);

    puttuple_common(state, &stup);

    MemoryContextSwitchTo(oldcontext);
}

void tuplesort_puttupleslot ( Tuplesortstate state,
TupleTableSlot slot 
)

Definition at line 1089 of file tuplesort.c.

References COPYTUP, MemoryContextSwitchTo(), puttuple_common(), and Tuplesortstate::sortcontext.

Referenced by advance_aggregates(), and ExecSort().

{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
    SortTuple   stup;

    /*
     * Copy the given tuple into memory we control, and decrease availMem.
     * Then call the common code.
     */
    COPYTUP(state, &stup, (void *) slot);

    puttuple_common(state, &stup);

    MemoryContextSwitchTo(oldcontext);
}

void tuplesort_rescan ( Tuplesortstate state  ) 
void tuplesort_restorepos ( Tuplesortstate state  ) 
void tuplesort_set_bound ( Tuplesortstate state,
int64  bound 
)

Definition at line 870 of file tuplesort.c.

References Assert, Tuplesortstate::bound, Tuplesortstate::bounded, Tuplesortstate::memtupcount, Tuplesortstate::status, and TSS_INITIAL.

Referenced by ExecSort().

{
    /* Assert we're called before loading any tuples */
    Assert(state->status == TSS_INITIAL);
    Assert(state->memtupcount == 0);
    Assert(!state->bounded);

#ifdef DEBUG_BOUNDED_SORT
    /* Honor GUC setting that disables the feature (for easy testing) */
    if (!optimize_bounded_sort)
        return;
#endif

    /* We want to be able to compute bound * 2, so limit the setting */
    if (bound > (int64) (INT_MAX / 2))
        return;

    state->bounded = true;
    state->bound = (int) bound;
}