1/*-------------------------------------------------------------------------
4 * Routines to handle sorting of relations.
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeSort.c
13 *-------------------------------------------------------------------------
25/* ----------------------------------------------------------------
28 * Sorts tuples from the outer subtree of the node using tuplesort,
29 * which saves the results in a temporary file or memory. After the
30 * initial call, returns a tuple from the file with each call.
32 * There are two distinct ways that this sort can be performed:
34 * 1) When the result is a single column we perform a Datum sort.
36 * 2) When the result contains multiple columns we perform a tuple sort.
38 * We could do this by always performing a tuple sort, however sorting
39 * Datums only can be significantly faster than sorting tuples,
40 * especially when the Datums are of a pass-by-value type.
46 * -- the outer child is prepared to return the first tuple.
47 * ----------------------------------------------------------------
61 * get state info from node
71 * If first time through, read all tuples from outer plan and pass them to
72 * tuplesort.c. Subsequent calls just fetch tuples from tuplesort.
86 * Want to scan subplan in the forward direction while creating the
92 * Initialize tuplesort module.
95 "calling tuplesort_begin");
107 plannode->sortOperators[0],
108 plannode->collations[0],
109 plannode->nullsFirst[0],
116 plannode->sortColIdx,
117 plannode->sortOperators,
118 plannode->collations,
119 plannode->nullsFirst,
128 * Scan the subplan and feed all the tuples to tuplesort using the
129 * appropriate method based on the type of sort we're doing.
163 * restore to user specified direction
168 * finally set the sorted flag to true
178 Assert(ParallelWorkerNumber <= node->shared_info->num_workers);
186 "retrieving tuple from tuplesort");
191 * Fetch the next sorted item from the appropriate tuplesort function. For
192 * datum sorts we must manage the slot ourselves and leave it clear when
193 * tuplesort_getdatum returns false to indicate there are no more datums.
194 * For tuple sorts, tuplesort_gettupleslot manages the slot for us and
195 * empties the slot when it runs out of tuples.
213/* ----------------------------------------------------------------
216 * Creates the run-time state information for the sort node
217 * produced by the planner and initializes its outer subtree.
218 * ----------------------------------------------------------------
227 "initializing sort node");
230 * create state structure
238 * We must have random access to the sort output to do backward scan or
239 * mark/restore. We also prefer to materialize the sort output if we
240 * might be called on to rewind and replay it many times.
251 * Miscellaneous initialization
253 * Sort nodes don't initialize their ExprContexts because they never call
254 * ExecQual or ExecProject.
258 * initialize child nodes
260 * We shield the child node from the need to support REWIND, BACKWARD, or
268 * Initialize scan slot and type.
273 * Initialize return slot and type. No need to initialize projection info
274 * because this node doesn't do projections.
282 * We perform a Datum sort when we're sorting just a single column,
283 * otherwise we perform a tuple sort.
285 if (outerTupDesc->
natts == 1)
291 "sort node initialized");
296/* ----------------------------------------------------------------
298 * ----------------------------------------------------------------
304 "shutting down sort node");
307 * Release tuplesort resources
314 * shut down the subplan
319 "sort node shutdown");
322/* ----------------------------------------------------------------
325 * Calls tuplesort to save the current position in the sorted file.
326 * ----------------------------------------------------------------
332 * if we haven't sorted yet, just return
340/* ----------------------------------------------------------------
343 * Calls tuplesort to restore the last saved sort file position.
344 * ----------------------------------------------------------------
350 * if we haven't sorted yet, just return.
356 * restore the scan to the previously marked position
367 * If we haven't sorted yet, just return. If outerplan's chgParam is not
368 * NULL then it will be re-scanned by ExecProcNode, else no reason to
374 /* must drop pointer to sort result tuple */
378 * If subnode is to be rescanned then we forget previous sort results; we
379 * have to re-read the subplan and re-sort. Also must re-sort if the
380 * bounded-sort parameters changed or we didn't select randomAccess.
382 * Otherwise we can just rewind and rescan the sorted output.
394 * if chgParam of subnode is not null then plan will be re-scanned by
395 * first ExecProcNode.
404/* ----------------------------------------------------------------
405 * Parallel Query Support
406 * ----------------------------------------------------------------
409/* ----------------------------------------------------------------
412 * Estimate space required to propagate sort statistics.
413 * ----------------------------------------------------------------
420 /* don't need this if not instrumenting or no workers */
430/* ----------------------------------------------------------------
431 * ExecSortInitializeDSM
433 * Initialize DSM space for sort statistics.
434 * ----------------------------------------------------------------
441 /* don't need this if not instrumenting or no workers */
448 /* ensure any unfilled slots will contain zeroes */
455/* ----------------------------------------------------------------
456 * ExecSortInitializeWorker
458 * Attach worker to DSM space for sort statistics.
459 * ----------------------------------------------------------------
469/* ----------------------------------------------------------------
470 * ExecSortRetrieveInstrumentation
472 * Transfer sort statistics from DSM to private memory.
473 * ----------------------------------------------------------------
void ExecReScan(PlanState *node)
void ExecEndNode(PlanState *node)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
const TupleTableSlotOps TTSOpsVirtual
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
const TupleTableSlotOps TTSOpsMinimalTuple
TupleDesc ExecGetResultType(PlanState *planstate)
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
#define outerPlanState(node)
#define EXEC_FLAG_BACKWARD
static TupleTableSlot * ExecProcNode(PlanState *node)
Assert(PointerIsAligned(start, uint64))
#define IsParallelWorker()
if(TABLE==NULL||TABLE_index==NULL)
#define CHECK_FOR_INTERRUPTS()
SortState * ExecInitSort(Sort *node, EState *estate, int eflags)
void ExecSortMarkPos(SortState *node)
static TupleTableSlot * ExecSort(PlanState *pstate)
void ExecSortInitializeWorker(SortState *node, ParallelWorkerContext *pwcxt)
void ExecReScanSort(SortState *node)
void ExecSortRestrPos(SortState *node)
void ExecSortEstimate(SortState *node, ParallelContext *pcxt)
void ExecSortInitializeDSM(SortState *node, ParallelContext *pcxt)
void ExecSortRetrieveInstrumentation(SortState *node)
void ExecEndSort(SortState *node)
#define castNode(_type_, nodeptr)
#define ScanDirectionIsForward(direction)
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
#define shm_toc_estimate_chunk(e, sz)
#define shm_toc_estimate_keys(e, cnt)
Size add_size(Size s1, Size s2)
Size mul_size(Size s1, Size s2)
ScanDirection es_direction
shm_toc_estimator estimator
Instrumentation * instrument
TupleTableSlot * ps_ResultTupleSlot
ProjectionInfo * ps_ProjInfo
ExecProcNodeMtd ExecProcNode
TuplesortInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
SharedSortInfo * shared_info
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
void tuplesort_rescan(Tuplesortstate *state)
void tuplesort_performsort(Tuplesortstate *state)
void tuplesort_get_stats(Tuplesortstate *state, TuplesortInstrumentation *stats)
void tuplesort_end(Tuplesortstate *state)
void tuplesort_markpos(Tuplesortstate *state)
void tuplesort_restorepos(Tuplesortstate *state)
void tuplesort_set_bound(Tuplesortstate *state, int64 bound)
#define TUPLESORT_RANDOMACCESS
#define TUPLESORT_ALLOWBOUNDED
struct TuplesortInstrumentation TuplesortInstrumentation
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, SortCoordinate coordinate, int sortopt)
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy, TupleTableSlot *slot, Datum *abbrev)
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, SortCoordinate coordinate, int sortopt)
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, bool copy, Datum *val, bool *isNull, Datum *abbrev)
static void slot_getsomeattrs(TupleTableSlot *slot, int attnum)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)