1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Adjust tuplesort API to have bitwise option flags

This replaces the bool flag for randomAccess.  An upcoming patch requires
adding another option, so instead of breaking the API for that, then
breaking it again one day if we add more options, let's just break it
once.  Any boolean options we add in the future will just make use of an
unused bit in the flags.

Any extensions making use of tuplesorts will need to update their code
to pass TUPLESORT_RANDOMACCESS instead of true for randomAccess.
TUPLESORT_NONE can be used for a set of empty options.

Author: David Rowley
Reviewed-by: Justin Pryzby
Discussion: https://postgr.es/m/CAApHDvoH4ASzsAOyHcxkuY01Qf%2B%2B8JJ0paw%2B03dk%2BW25tQEcNQ%40mail.gmail.com
This commit is contained in:
David Rowley
2022-04-04 22:24:59 +12:00
parent 1b0d9aa4f7
commit 77bae396df
11 changed files with 99 additions and 73 deletions

View File

@ -271,7 +271,7 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
index, index,
maintenance_work_mem, maintenance_work_mem,
NULL, NULL,
false); TUPLESORT_NONE);
/* Scan the table, adding all tuples to the tuplesort */ /* Scan the table, adding all tuples to the tuplesort */
reltuples = table_index_build_scan(heap, index, indexInfo, true, true, reltuples = table_index_build_scan(heap, index, indexInfo, true, true,

View File

@ -86,7 +86,7 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
hspool->max_buckets, hspool->max_buckets,
maintenance_work_mem, maintenance_work_mem,
NULL, NULL,
false); TUPLESORT_NONE);
return hspool; return hspool;
} }

View File

@ -726,7 +726,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
if (use_sort) if (use_sort)
tuplesort = tuplesort_begin_cluster(oldTupDesc, OldIndex, tuplesort = tuplesort_begin_cluster(oldTupDesc, OldIndex,
maintenance_work_mem, maintenance_work_mem,
NULL, false); NULL, TUPLESORT_NONE);
else else
tuplesort = NULL; tuplesort = NULL;

View File

@ -436,7 +436,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
tuplesort_begin_index_btree(heap, index, buildstate->isunique, tuplesort_begin_index_btree(heap, index, buildstate->isunique,
buildstate->nulls_not_distinct, buildstate->nulls_not_distinct,
maintenance_work_mem, coordinate, maintenance_work_mem, coordinate,
false); TUPLESORT_NONE);
/* /*
* If building a unique index, put dead tuples in a second spool to keep * If building a unique index, put dead tuples in a second spool to keep
@ -475,7 +475,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
*/ */
buildstate->spool2->sortstate = buildstate->spool2->sortstate =
tuplesort_begin_index_btree(heap, index, false, false, work_mem, tuplesort_begin_index_btree(heap, index, false, false, work_mem,
coordinate2, false); coordinate2, TUPLESORT_NONE);
} }
/* Fill spool using either serial or parallel heap scan */ /* Fill spool using either serial or parallel heap scan */
@ -1939,7 +1939,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
btspool->isunique, btspool->isunique,
btspool->nulls_not_distinct, btspool->nulls_not_distinct,
sortmem, coordinate, sortmem, coordinate,
false); TUPLESORT_NONE);
/* /*
* Just as with serial case, there may be a second spool. If so, a * Just as with serial case, there may be a second spool. If so, a

View File

@ -3364,7 +3364,7 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
state.tuplesort = tuplesort_begin_datum(INT8OID, Int8LessOperator, state.tuplesort = tuplesort_begin_datum(INT8OID, Int8LessOperator,
InvalidOid, false, InvalidOid, false,
maintenance_work_mem, maintenance_work_mem,
NULL, false); NULL, TUPLESORT_NONE);
state.htups = state.itups = state.tups_inserted = 0; state.htups = state.itups = state.tups_inserted = 0;
/* ambulkdelete updates progress metrics */ /* ambulkdelete updates progress metrics */

View File

@ -530,7 +530,7 @@ initialize_phase(AggState *aggstate, int newphase)
sortnode->collations, sortnode->collations,
sortnode->nullsFirst, sortnode->nullsFirst,
work_mem, work_mem,
NULL, false); NULL, TUPLESORT_NONE);
} }
aggstate->current_phase = newphase; aggstate->current_phase = newphase;
@ -607,7 +607,7 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
pertrans->sortOperators[0], pertrans->sortOperators[0],
pertrans->sortCollations[0], pertrans->sortCollations[0],
pertrans->sortNullsFirst[0], pertrans->sortNullsFirst[0],
work_mem, NULL, false); work_mem, NULL, TUPLESORT_NONE);
} }
else else
pertrans->sortstates[aggstate->current_set] = pertrans->sortstates[aggstate->current_set] =
@ -617,7 +617,7 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
pertrans->sortOperators, pertrans->sortOperators,
pertrans->sortCollations, pertrans->sortCollations,
pertrans->sortNullsFirst, pertrans->sortNullsFirst,
work_mem, NULL, false); work_mem, NULL, TUPLESORT_NONE);
} }
/* /*

View File

@ -315,7 +315,7 @@ switchToPresortedPrefixMode(PlanState *pstate)
&(plannode->sort.nullsFirst[nPresortedCols]), &(plannode->sort.nullsFirst[nPresortedCols]),
work_mem, work_mem,
NULL, NULL,
false); TUPLESORT_NONE);
node->prefixsort_state = prefixsort_state; node->prefixsort_state = prefixsort_state;
} }
else else
@ -616,7 +616,7 @@ ExecIncrementalSort(PlanState *pstate)
plannode->sort.nullsFirst, plannode->sort.nullsFirst,
work_mem, work_mem,
NULL, NULL,
false); TUPLESORT_NONE);
node->fullsort_state = fullsort_state; node->fullsort_state = fullsort_state;
} }
else else

View File

@ -77,6 +77,7 @@ ExecSort(PlanState *pstate)
Sort *plannode = (Sort *) node->ss.ps.plan; Sort *plannode = (Sort *) node->ss.ps.plan;
PlanState *outerNode; PlanState *outerNode;
TupleDesc tupDesc; TupleDesc tupDesc;
int tuplesortopts = TUPLESORT_NONE;
SO1_printf("ExecSort: %s\n", SO1_printf("ExecSort: %s\n",
"sorting subplan"); "sorting subplan");
@ -96,6 +97,9 @@ ExecSort(PlanState *pstate)
outerNode = outerPlanState(node); outerNode = outerPlanState(node);
tupDesc = ExecGetResultType(outerNode); tupDesc = ExecGetResultType(outerNode);
if (node->randomAccess)
tuplesortopts |= TUPLESORT_RANDOMACCESS;
if (node->datumSort) if (node->datumSort)
tuplesortstate = tuplesort_begin_datum(TupleDescAttr(tupDesc, 0)->atttypid, tuplesortstate = tuplesort_begin_datum(TupleDescAttr(tupDesc, 0)->atttypid,
plannode->sortOperators[0], plannode->sortOperators[0],
@ -103,7 +107,7 @@ ExecSort(PlanState *pstate)
plannode->nullsFirst[0], plannode->nullsFirst[0],
work_mem, work_mem,
NULL, NULL,
node->randomAccess); tuplesortopts);
else else
tuplesortstate = tuplesort_begin_heap(tupDesc, tuplesortstate = tuplesort_begin_heap(tupDesc,
plannode->numCols, plannode->numCols,
@ -113,7 +117,7 @@ ExecSort(PlanState *pstate)
plannode->nullsFirst, plannode->nullsFirst,
work_mem, work_mem,
NULL, NULL,
node->randomAccess); tuplesortopts);
if (node->bounded) if (node->bounded)
tuplesort_set_bound(tuplesortstate, node->bound); tuplesort_set_bound(tuplesortstate, node->bound);
node->tuplesortstate = (void *) tuplesortstate; node->tuplesortstate = (void *) tuplesortstate;

View File

@ -118,6 +118,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
OSAPerQueryState *qstate; OSAPerQueryState *qstate;
MemoryContext gcontext; MemoryContext gcontext;
MemoryContext oldcontext; MemoryContext oldcontext;
int tuplesortopt;
/* /*
* Check we're called as aggregate (and not a window function), and get * Check we're called as aggregate (and not a window function), and get
@ -283,6 +284,11 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
osastate->qstate = qstate; osastate->qstate = qstate;
osastate->gcontext = gcontext; osastate->gcontext = gcontext;
tuplesortopt = TUPLESORT_NONE;
if (qstate->rescan_needed)
tuplesortopt |= TUPLESORT_RANDOMACCESS;
/* /*
* Initialize tuplesort object. * Initialize tuplesort object.
*/ */
@ -295,7 +301,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
qstate->sortNullsFirsts, qstate->sortNullsFirsts,
work_mem, work_mem,
NULL, NULL,
qstate->rescan_needed); tuplesortopt);
else else
osastate->sortstate = tuplesort_begin_datum(qstate->sortColType, osastate->sortstate = tuplesort_begin_datum(qstate->sortColType,
qstate->sortOperator, qstate->sortOperator,
@ -303,7 +309,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
qstate->sortNullsFirst, qstate->sortNullsFirst,
work_mem, work_mem,
NULL, NULL,
qstate->rescan_needed); tuplesortopt);
osastate->number_of_rows = 0; osastate->number_of_rows = 0;
osastate->sort_done = false; osastate->sort_done = false;

View File

@ -246,7 +246,7 @@ struct Tuplesortstate
{ {
TupSortStatus status; /* enumerated value as shown above */ TupSortStatus status; /* enumerated value as shown above */
int nKeys; /* number of columns in sort key */ int nKeys; /* number of columns in sort key */
bool randomAccess; /* did caller request random access? */ int sortopt; /* Bitmask of flags used to setup sort */
bool bounded; /* did caller specify a maximum number of bool bounded; /* did caller specify a maximum number of
* tuples to return? */ * tuples to return? */
bool boundUsed; /* true if we made use of a bounded heap */ bool boundUsed; /* true if we made use of a bounded heap */
@ -564,12 +564,12 @@ struct Sharedsort
* may or may not match the in-memory representation of the tuple --- * may or may not match the in-memory representation of the tuple ---
* any conversion needed is the job of the writetup and readtup routines. * any conversion needed is the job of the writetup and readtup routines.
* *
* If state->randomAccess is true, then the stored representation of the * If state->sortopt contains TUPLESORT_RANDOMACCESS, then the stored
* tuple must be followed by another "unsigned int" that is a copy of the * representation of the tuple must be followed by another "unsigned int" that
* length --- so the total tape space used is actually sizeof(unsigned int) * is a copy of the length --- so the total tape space used is actually
* more than the stored length value. This allows read-backwards. When * sizeof(unsigned int) more than the stored length value. This allows
* randomAccess is not true, the write/read routines may omit the extra * read-backwards. When the random access flag was not specified, the
* length word. * write/read routines may omit the extra length word.
* *
* writetup is expected to write both length words as well as the tuple * writetup is expected to write both length words as well as the tuple
* data. When readtup is called, the tape is positioned just after the * data. When readtup is called, the tape is positioned just after the
@ -614,7 +614,7 @@ struct Sharedsort
static Tuplesortstate *tuplesort_begin_common(int workMem, static Tuplesortstate *tuplesort_begin_common(int workMem,
SortCoordinate coordinate, SortCoordinate coordinate,
bool randomAccess); int sortopt);
static void tuplesort_begin_batch(Tuplesortstate *state); static void tuplesort_begin_batch(Tuplesortstate *state);
static void puttuple_common(Tuplesortstate *state, SortTuple *tuple); static void puttuple_common(Tuplesortstate *state, SortTuple *tuple);
static bool consider_abort_common(Tuplesortstate *state); static bool consider_abort_common(Tuplesortstate *state);
@ -806,21 +806,20 @@ qsort_tuple_int32_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
* Each variant of tuplesort_begin has a workMem parameter specifying the * Each variant of tuplesort_begin has a workMem parameter specifying the
* maximum number of kilobytes of RAM to use before spilling data to disk. * maximum number of kilobytes of RAM to use before spilling data to disk.
* (The normal value of this parameter is work_mem, but some callers use * (The normal value of this parameter is work_mem, but some callers use
* other values.) Each variant also has a randomAccess parameter specifying * other values.) Each variant also has a sortopt which is a bitmask of
* whether the caller needs non-sequential access to the sort result. * sort options. See TUPLESORT_* definitions in tuplesort.h
*/ */
static Tuplesortstate * static Tuplesortstate *
tuplesort_begin_common(int workMem, SortCoordinate coordinate, tuplesort_begin_common(int workMem, SortCoordinate coordinate, int sortopt)
bool randomAccess)
{ {
Tuplesortstate *state; Tuplesortstate *state;
MemoryContext maincontext; MemoryContext maincontext;
MemoryContext sortcontext; MemoryContext sortcontext;
MemoryContext oldcontext; MemoryContext oldcontext;
/* See leader_takeover_tapes() remarks on randomAccess support */ /* See leader_takeover_tapes() remarks on random access support */
if (coordinate && randomAccess) if (coordinate && (sortopt & TUPLESORT_RANDOMACCESS))
elog(ERROR, "random access disallowed under parallel sort"); elog(ERROR, "random access disallowed under parallel sort");
/* /*
@ -857,7 +856,7 @@ tuplesort_begin_common(int workMem, SortCoordinate coordinate,
pg_rusage_init(&state->ru_start); pg_rusage_init(&state->ru_start);
#endif #endif
state->randomAccess = randomAccess; state->sortopt = sortopt;
state->tuples = true; state->tuples = true;
/* /*
@ -991,10 +990,10 @@ tuplesort_begin_heap(TupleDesc tupDesc,
int nkeys, AttrNumber *attNums, int nkeys, AttrNumber *attNums,
Oid *sortOperators, Oid *sortCollations, Oid *sortOperators, Oid *sortCollations,
bool *nullsFirstFlags, bool *nullsFirstFlags,
int workMem, SortCoordinate coordinate, bool randomAccess) int workMem, SortCoordinate coordinate, int sortopt)
{ {
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate, Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
randomAccess); sortopt);
MemoryContext oldcontext; MemoryContext oldcontext;
int i; int i;
@ -1006,7 +1005,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
if (trace_sort) if (trace_sort)
elog(LOG, elog(LOG,
"begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c", "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c",
nkeys, workMem, randomAccess ? 't' : 'f'); nkeys, workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif #endif
state->nKeys = nkeys; state->nKeys = nkeys;
@ -1015,7 +1014,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
false, /* no unique check */ false, /* no unique check */
nkeys, nkeys,
workMem, workMem,
randomAccess, sortopt & TUPLESORT_RANDOMACCESS,
PARALLEL_SORT(state)); PARALLEL_SORT(state));
state->comparetup = comparetup_heap; state->comparetup = comparetup_heap;
@ -1065,10 +1064,10 @@ Tuplesortstate *
tuplesort_begin_cluster(TupleDesc tupDesc, tuplesort_begin_cluster(TupleDesc tupDesc,
Relation indexRel, Relation indexRel,
int workMem, int workMem,
SortCoordinate coordinate, bool randomAccess) SortCoordinate coordinate, int sortopt)
{ {
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate, Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
randomAccess); sortopt);
BTScanInsert indexScanKey; BTScanInsert indexScanKey;
MemoryContext oldcontext; MemoryContext oldcontext;
int i; int i;
@ -1082,7 +1081,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
elog(LOG, elog(LOG,
"begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c", "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c",
RelationGetNumberOfAttributes(indexRel), RelationGetNumberOfAttributes(indexRel),
workMem, randomAccess ? 't' : 'f'); workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif #endif
state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel); state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
@ -1091,7 +1090,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
false, /* no unique check */ false, /* no unique check */
state->nKeys, state->nKeys,
workMem, workMem,
randomAccess, sortopt & TUPLESORT_RANDOMACCESS,
PARALLEL_SORT(state)); PARALLEL_SORT(state));
state->comparetup = comparetup_cluster; state->comparetup = comparetup_cluster;
@ -1172,10 +1171,10 @@ tuplesort_begin_index_btree(Relation heapRel,
bool uniqueNullsNotDistinct, bool uniqueNullsNotDistinct,
int workMem, int workMem,
SortCoordinate coordinate, SortCoordinate coordinate,
bool randomAccess) int sortopt)
{ {
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate, Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
randomAccess); sortopt);
BTScanInsert indexScanKey; BTScanInsert indexScanKey;
MemoryContext oldcontext; MemoryContext oldcontext;
int i; int i;
@ -1187,7 +1186,7 @@ tuplesort_begin_index_btree(Relation heapRel,
elog(LOG, elog(LOG,
"begin index sort: unique = %c, workMem = %d, randomAccess = %c", "begin index sort: unique = %c, workMem = %d, randomAccess = %c",
enforceUnique ? 't' : 'f', enforceUnique ? 't' : 'f',
workMem, randomAccess ? 't' : 'f'); workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif #endif
state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel); state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
@ -1196,7 +1195,7 @@ tuplesort_begin_index_btree(Relation heapRel,
enforceUnique, enforceUnique,
state->nKeys, state->nKeys,
workMem, workMem,
randomAccess, sortopt & TUPLESORT_RANDOMACCESS,
PARALLEL_SORT(state)); PARALLEL_SORT(state));
state->comparetup = comparetup_index_btree; state->comparetup = comparetup_index_btree;
@ -1254,10 +1253,10 @@ tuplesort_begin_index_hash(Relation heapRel,
uint32 max_buckets, uint32 max_buckets,
int workMem, int workMem,
SortCoordinate coordinate, SortCoordinate coordinate,
bool randomAccess) int sortopt)
{ {
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate, Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
randomAccess); sortopt);
MemoryContext oldcontext; MemoryContext oldcontext;
oldcontext = MemoryContextSwitchTo(state->maincontext); oldcontext = MemoryContextSwitchTo(state->maincontext);
@ -1270,7 +1269,8 @@ tuplesort_begin_index_hash(Relation heapRel,
high_mask, high_mask,
low_mask, low_mask,
max_buckets, max_buckets,
workMem, randomAccess ? 't' : 'f'); workMem,
sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif #endif
state->nKeys = 1; /* Only one sort column, the hash code */ state->nKeys = 1; /* Only one sort column, the hash code */
@ -1298,10 +1298,10 @@ tuplesort_begin_index_gist(Relation heapRel,
Relation indexRel, Relation indexRel,
int workMem, int workMem,
SortCoordinate coordinate, SortCoordinate coordinate,
bool randomAccess) int sortopt)
{ {
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate, Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
randomAccess); sortopt);
MemoryContext oldcontext; MemoryContext oldcontext;
int i; int i;
@ -1311,7 +1311,7 @@ tuplesort_begin_index_gist(Relation heapRel,
if (trace_sort) if (trace_sort)
elog(LOG, elog(LOG,
"begin index sort: workMem = %d, randomAccess = %c", "begin index sort: workMem = %d, randomAccess = %c",
workMem, randomAccess ? 't' : 'f'); workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif #endif
state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel); state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
@ -1354,10 +1354,10 @@ tuplesort_begin_index_gist(Relation heapRel,
Tuplesortstate * Tuplesortstate *
tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
bool nullsFirstFlag, int workMem, bool nullsFirstFlag, int workMem,
SortCoordinate coordinate, bool randomAccess) SortCoordinate coordinate, int sortopt)
{ {
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate, Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
randomAccess); sortopt);
MemoryContext oldcontext; MemoryContext oldcontext;
int16 typlen; int16 typlen;
bool typbyval; bool typbyval;
@ -1368,7 +1368,7 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
if (trace_sort) if (trace_sort)
elog(LOG, elog(LOG,
"begin datum sort: workMem = %d, randomAccess = %c", "begin datum sort: workMem = %d, randomAccess = %c",
workMem, randomAccess ? 't' : 'f'); workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif #endif
state->nKeys = 1; /* always a one-column sort */ state->nKeys = 1; /* always a one-column sort */
@ -1377,7 +1377,7 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
false, /* no unique check */ false, /* no unique check */
1, 1,
workMem, workMem,
randomAccess, sortopt & TUPLESORT_RANDOMACCESS,
PARALLEL_SORT(state)); PARALLEL_SORT(state));
state->comparetup = comparetup_datum; state->comparetup = comparetup_datum;
@ -2272,7 +2272,7 @@ tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
switch (state->status) switch (state->status)
{ {
case TSS_SORTEDINMEM: case TSS_SORTEDINMEM:
Assert(forward || state->randomAccess); Assert(forward || state->sortopt & TUPLESORT_RANDOMACCESS);
Assert(!state->slabAllocatorUsed); Assert(!state->slabAllocatorUsed);
if (forward) if (forward)
{ {
@ -2316,7 +2316,7 @@ tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
break; break;
case TSS_SORTEDONTAPE: case TSS_SORTEDONTAPE:
Assert(forward || state->randomAccess); Assert(forward || state->sortopt & TUPLESORT_RANDOMACCESS);
Assert(state->slabAllocatorUsed); Assert(state->slabAllocatorUsed);
/* /*
@ -3091,7 +3091,8 @@ mergeruns(Tuplesortstate *state)
* sorted tape, we can stop at this point and do the final merge * sorted tape, we can stop at this point and do the final merge
* on-the-fly. * on-the-fly.
*/ */
if (!state->randomAccess && state->nInputRuns <= state->nInputTapes if ((state->sortopt & TUPLESORT_RANDOMACCESS) == 0
&& state->nInputRuns <= state->nInputTapes
&& !WORKER(state)) && !WORKER(state))
{ {
/* Tell logtape.c we won't be writing anymore */ /* Tell logtape.c we won't be writing anymore */
@ -3337,7 +3338,7 @@ tuplesort_rescan(Tuplesortstate *state)
{ {
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
Assert(state->randomAccess); Assert(state->sortopt & TUPLESORT_RANDOMACCESS);
switch (state->status) switch (state->status)
{ {
@ -3370,7 +3371,7 @@ tuplesort_markpos(Tuplesortstate *state)
{ {
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
Assert(state->randomAccess); Assert(state->sortopt & TUPLESORT_RANDOMACCESS);
switch (state->status) switch (state->status)
{ {
@ -3401,7 +3402,7 @@ tuplesort_restorepos(Tuplesortstate *state)
{ {
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
Assert(state->randomAccess); Assert(state->sortopt & TUPLESORT_RANDOMACCESS);
switch (state->status) switch (state->status)
{ {
@ -3998,7 +3999,8 @@ writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen)); LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
LogicalTapeWrite(tape, (void *) tupbody, tupbodylen); LogicalTapeWrite(tape, (void *) tupbody, tupbodylen);
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen)); LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
if (!state->slabAllocatorUsed) if (!state->slabAllocatorUsed)
@ -4021,7 +4023,8 @@ readtup_heap(Tuplesortstate *state, SortTuple *stup,
/* read in the tuple proper */ /* read in the tuple proper */
tuple->t_len = tuplen; tuple->t_len = tuplen;
LogicalTapeReadExact(tape, tupbody, tupbodylen); LogicalTapeReadExact(tape, tupbody, tupbodylen);
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
stup->tuple = (void *) tuple; stup->tuple = (void *) tuple;
/* set up first-column key value */ /* set up first-column key value */
@ -4233,7 +4236,8 @@ writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
LogicalTapeWrite(tape, &tuplen, sizeof(tuplen)); LogicalTapeWrite(tape, &tuplen, sizeof(tuplen));
LogicalTapeWrite(tape, &tuple->t_self, sizeof(ItemPointerData)); LogicalTapeWrite(tape, &tuple->t_self, sizeof(ItemPointerData));
LogicalTapeWrite(tape, tuple->t_data, tuple->t_len); LogicalTapeWrite(tape, tuple->t_data, tuple->t_len);
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, &tuplen, sizeof(tuplen)); LogicalTapeWrite(tape, &tuplen, sizeof(tuplen));
if (!state->slabAllocatorUsed) if (!state->slabAllocatorUsed)
@ -4259,7 +4263,8 @@ readtup_cluster(Tuplesortstate *state, SortTuple *stup,
tuple->t_tableOid = InvalidOid; tuple->t_tableOid = InvalidOid;
/* Read in the tuple body */ /* Read in the tuple body */
LogicalTapeReadExact(tape, tuple->t_data, tuple->t_len); LogicalTapeReadExact(tape, tuple->t_data, tuple->t_len);
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
stup->tuple = (void *) tuple; stup->tuple = (void *) tuple;
/* set up first-column key value, if it's a simple column */ /* set up first-column key value, if it's a simple column */
@ -4483,7 +4488,8 @@ writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
tuplen = IndexTupleSize(tuple) + sizeof(tuplen); tuplen = IndexTupleSize(tuple) + sizeof(tuplen);
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen)); LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
LogicalTapeWrite(tape, (void *) tuple, IndexTupleSize(tuple)); LogicalTapeWrite(tape, (void *) tuple, IndexTupleSize(tuple));
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen)); LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
if (!state->slabAllocatorUsed) if (!state->slabAllocatorUsed)
@ -4501,7 +4507,8 @@ readtup_index(Tuplesortstate *state, SortTuple *stup,
IndexTuple tuple = (IndexTuple) readtup_alloc(state, tuplen); IndexTuple tuple = (IndexTuple) readtup_alloc(state, tuplen);
LogicalTapeReadExact(tape, tuple, tuplen); LogicalTapeReadExact(tape, tuple, tuplen);
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
stup->tuple = (void *) tuple; stup->tuple = (void *) tuple;
/* set up first-column key value */ /* set up first-column key value */
@ -4571,7 +4578,8 @@ writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen)); LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen));
LogicalTapeWrite(tape, waddr, tuplen); LogicalTapeWrite(tape, waddr, tuplen);
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen)); LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen));
if (!state->slabAllocatorUsed && stup->tuple) if (!state->slabAllocatorUsed && stup->tuple)
@ -4611,7 +4619,8 @@ readtup_datum(Tuplesortstate *state, SortTuple *stup,
stup->tuple = raddr; stup->tuple = raddr;
} }
if (state->randomAccess) /* need trailing length word? */ if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
} }

View File

@ -86,6 +86,12 @@ typedef enum
SORT_SPACE_TYPE_MEMORY SORT_SPACE_TYPE_MEMORY
} TuplesortSpaceType; } TuplesortSpaceType;
/* Bitwise option flags for tuple sorts */
#define TUPLESORT_NONE 0
/* specifies whether non-sequential access to the sort result is required */
#define TUPLESORT_RANDOMACCESS (1 << 0)
typedef struct TuplesortInstrumentation typedef struct TuplesortInstrumentation
{ {
TuplesortMethod sortMethod; /* sort algorithm used */ TuplesortMethod sortMethod; /* sort algorithm used */
@ -201,32 +207,33 @@ extern Tuplesortstate *tuplesort_begin_heap(TupleDesc tupDesc,
Oid *sortOperators, Oid *sortCollations, Oid *sortOperators, Oid *sortCollations,
bool *nullsFirstFlags, bool *nullsFirstFlags,
int workMem, SortCoordinate coordinate, int workMem, SortCoordinate coordinate,
bool randomAccess); int sortopt);
extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc, extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc,
Relation indexRel, int workMem, Relation indexRel, int workMem,
SortCoordinate coordinate, bool randomAccess); SortCoordinate coordinate,
int sortopt);
extern Tuplesortstate *tuplesort_begin_index_btree(Relation heapRel, extern Tuplesortstate *tuplesort_begin_index_btree(Relation heapRel,
Relation indexRel, Relation indexRel,
bool enforceUnique, bool enforceUnique,
bool uniqueNullsNotDistinct, bool uniqueNullsNotDistinct,
int workMem, SortCoordinate coordinate, int workMem, SortCoordinate coordinate,
bool randomAccess); int sortopt);
extern Tuplesortstate *tuplesort_begin_index_hash(Relation heapRel, extern Tuplesortstate *tuplesort_begin_index_hash(Relation heapRel,
Relation indexRel, Relation indexRel,
uint32 high_mask, uint32 high_mask,
uint32 low_mask, uint32 low_mask,
uint32 max_buckets, uint32 max_buckets,
int workMem, SortCoordinate coordinate, int workMem, SortCoordinate coordinate,
bool randomAccess); int sortopt);
extern Tuplesortstate *tuplesort_begin_index_gist(Relation heapRel, extern Tuplesortstate *tuplesort_begin_index_gist(Relation heapRel,
Relation indexRel, Relation indexRel,
int workMem, SortCoordinate coordinate, int workMem, SortCoordinate coordinate,
bool randomAccess); int sortopt);
extern Tuplesortstate *tuplesort_begin_datum(Oid datumType, extern Tuplesortstate *tuplesort_begin_datum(Oid datumType,
Oid sortOperator, Oid sortCollation, Oid sortOperator, Oid sortCollation,
bool nullsFirstFlag, bool nullsFirstFlag,
int workMem, SortCoordinate coordinate, int workMem, SortCoordinate coordinate,
bool randomAccess); int sortopt);
extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound); extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
extern bool tuplesort_used_bound(Tuplesortstate *state); extern bool tuplesort_used_bound(Tuplesortstate *state);