#include "access/itup.h"#include "executor/tuptable.h"#include "fmgr.h"#include "utils/relcache.h"

Go to the source code of this file.
| typedef struct Tuplesortstate Tuplesortstate |
Definition at line 32 of file tuplesort.h.
| 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 | ) |
Definition at line 2369 of file tuplesort.c.
References Assert, Tuplesortstate::current, elog, Tuplesortstate::eof_reached, ERROR, LogicalTapeTell(), Tuplesortstate::markpos_block, Tuplesortstate::markpos_eof, Tuplesortstate::markpos_offset, MemoryContextSwitchTo(), Tuplesortstate::randomAccess, Tuplesortstate::result_tape, Tuplesortstate::sortcontext, Tuplesortstate::status, Tuplesortstate::tapeset, TSS_SORTEDINMEM, and TSS_SORTEDONTAPE.
Referenced by ExecSortMarkPos().
{
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
Assert(state->randomAccess);
switch (state->status)
{
case TSS_SORTEDINMEM:
state->markpos_offset = state->current;
state->markpos_eof = state->eof_reached;
break;
case TSS_SORTEDONTAPE:
LogicalTapeTell(state->tapeset,
state->result_tape,
&state->markpos_block,
&state->markpos_offset);
state->markpos_eof = state->eof_reached;
break;
default:
elog(ERROR, "invalid tuplesort state");
break;
}
MemoryContextSwitchTo(oldcontext);
}
| 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 | ) |
Definition at line 2334 of file tuplesort.c.
References Assert, Tuplesortstate::current, elog, Tuplesortstate::eof_reached, ERROR, LogicalTapeRewind(), Tuplesortstate::markpos_block, Tuplesortstate::markpos_eof, Tuplesortstate::markpos_offset, MemoryContextSwitchTo(), Tuplesortstate::randomAccess, Tuplesortstate::result_tape, Tuplesortstate::sortcontext, Tuplesortstate::status, Tuplesortstate::tapeset, TSS_SORTEDINMEM, and TSS_SORTEDONTAPE.
Referenced by ExecReScanSort().
{
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
Assert(state->randomAccess);
switch (state->status)
{
case TSS_SORTEDINMEM:
state->current = 0;
state->eof_reached = false;
state->markpos_offset = 0;
state->markpos_eof = false;
break;
case TSS_SORTEDONTAPE:
LogicalTapeRewind(state->tapeset,
state->result_tape,
false);
state->eof_reached = false;
state->markpos_block = 0L;
state->markpos_offset = 0;
state->markpos_eof = false;
break;
default:
elog(ERROR, "invalid tuplesort state");
break;
}
MemoryContextSwitchTo(oldcontext);
}
| void tuplesort_restorepos | ( | Tuplesortstate * | state | ) |
Definition at line 2401 of file tuplesort.c.
References Assert, Tuplesortstate::current, elog, Tuplesortstate::eof_reached, ERROR, LogicalTapeSeek(), Tuplesortstate::markpos_block, Tuplesortstate::markpos_eof, Tuplesortstate::markpos_offset, MemoryContextSwitchTo(), Tuplesortstate::randomAccess, Tuplesortstate::result_tape, Tuplesortstate::sortcontext, Tuplesortstate::status, Tuplesortstate::tapeset, TSS_SORTEDINMEM, and TSS_SORTEDONTAPE.
Referenced by ExecSortRestrPos().
{
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
Assert(state->randomAccess);
switch (state->status)
{
case TSS_SORTEDINMEM:
state->current = state->markpos_offset;
state->eof_reached = state->markpos_eof;
break;
case TSS_SORTEDONTAPE:
if (!LogicalTapeSeek(state->tapeset,
state->result_tape,
state->markpos_block,
state->markpos_offset))
elog(ERROR, "tuplesort_restorepos failed");
state->eof_reached = state->markpos_eof;
break;
default:
elog(ERROR, "invalid tuplesort state");
break;
}
MemoryContextSwitchTo(oldcontext);
}
| 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;
}
1.7.1