PostgreSQL Source Code  git master
nodeSort.c File Reference
#include "postgres.h"
#include "access/parallel.h"
#include "executor/execdebug.h"
#include "executor/nodeSort.h"
#include "miscadmin.h"
#include "utils/tuplesort.h"
Include dependency graph for nodeSort.c:

Go to the source code of this file.

Functions

static TupleTableSlotExecSort (PlanState *pstate)
 
SortStateExecInitSort (Sort *node, EState *estate, int eflags)
 
void ExecEndSort (SortState *node)
 
void ExecSortMarkPos (SortState *node)
 
void ExecSortRestrPos (SortState *node)
 
void ExecReScanSort (SortState *node)
 
void ExecSortEstimate (SortState *node, ParallelContext *pcxt)
 
void ExecSortInitializeDSM (SortState *node, ParallelContext *pcxt)
 
void ExecSortInitializeWorker (SortState *node, ParallelWorkerContext *pwcxt)
 
void ExecSortRetrieveInstrumentation (SortState *node)
 

Function Documentation

◆ ExecEndSort()

void ExecEndSort ( SortState node)

Definition at line 297 of file nodeSort.c.

298 {
299  SO1_printf("ExecEndSort: %s\n",
300  "shutting down sort node");
301 
302  /*
303  * clean out the tuple table
304  */
306  /* must drop pointer to sort result tuple */
308 
309  /*
310  * Release tuplesort resources
311  */
312  if (node->tuplesortstate != NULL)
314  node->tuplesortstate = NULL;
315 
316  /*
317  * shut down the subplan
318  */
320 
321  SO1_printf("ExecEndSort: %s\n",
322  "sort node shutdown");
323 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:556
#define SO1_printf(s, p)
Definition: execdebug.h:93
#define outerPlanState(node)
Definition: execnodes.h:1094
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1036
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1426
PlanState ps
Definition: execnodes.h:1423
void * tuplesortstate
Definition: execnodes.h:2202
ScanState ss
Definition: execnodes.h:2195
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1620
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425

References ExecClearTuple(), ExecEndNode(), outerPlanState, ScanState::ps, PlanState::ps_ResultTupleSlot, SO1_printf, SortState::ss, ScanState::ss_ScanTupleSlot, tuplesort_end(), and SortState::tuplesortstate.

Referenced by ExecEndNode().

◆ ExecInitSort()

SortState* ExecInitSort ( Sort node,
EState estate,
int  eflags 
)

Definition at line 220 of file nodeSort.c.

221 {
222  SortState *sortstate;
223 
224  SO1_printf("ExecInitSort: %s\n",
225  "initializing sort node");
226 
227  /*
228  * create state structure
229  */
230  sortstate = makeNode(SortState);
231  sortstate->ss.ps.plan = (Plan *) node;
232  sortstate->ss.ps.state = estate;
233  sortstate->ss.ps.ExecProcNode = ExecSort;
234 
235  /*
236  * We must have random access to the sort output to do backward scan or
237  * mark/restore. We also prefer to materialize the sort output if we
238  * might be called on to rewind and replay it many times.
239  */
240  sortstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
242  EXEC_FLAG_MARK)) != 0;
243 
244  sortstate->bounded = false;
245  sortstate->sort_Done = false;
246  sortstate->tuplesortstate = NULL;
247 
248  /*
249  * Miscellaneous initialization
250  *
251  * Sort nodes don't initialize their ExprContexts because they never call
252  * ExecQual or ExecProject.
253  */
254 
255  /*
256  * initialize child nodes
257  *
258  * We shield the child node from the need to support REWIND, BACKWARD, or
259  * MARK/RESTORE.
260  */
262 
263  outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate, eflags);
264 
265  /*
266  * Initialize scan slot and type.
267  */
268  ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss, &TTSOpsVirtual);
269 
270  /*
271  * Initialize return slot and type. No need to initialize projection info
272  * because this node doesn't do projections.
273  */
275  sortstate->ss.ps.ps_ProjInfo = NULL;
276 
277  /*
278  * We perform a Datum sort when we're sorting just a single column,
279  * otherwise we perform a tuple sort.
280  */
281  if (ExecGetResultType(outerPlanState(sortstate))->natts == 1)
282  sortstate->datumSort = true;
283  else
284  sortstate->datumSort = false;
285 
286  SO1_printf("ExecInitSort: %s\n",
287  "sort node initialized");
288 
289  return sortstate;
290 }
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:141
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1799
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:490
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
Definition: execUtils.c:682
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define EXEC_FLAG_REWIND
Definition: executor.h:57
#define EXEC_FLAG_MARK
Definition: executor.h:59
static TupleTableSlot * ExecSort(PlanState *pstate)
Definition: nodeSort.c:50
#define makeNode(_type_)
Definition: nodes.h:621
#define outerPlan(node)
Definition: plannodes.h:172
Plan * plan
Definition: execnodes.h:998
EState * state
Definition: execnodes.h:1000
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1038
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1004
bool sort_Done
Definition: execnodes.h:2199
bool randomAccess
Definition: execnodes.h:2196
bool datumSort
Definition: execnodes.h:2204
bool bounded
Definition: execnodes.h:2197

References SortState::bounded, SortState::datumSort, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecCreateScanSlotFromOuterPlan(), ExecGetResultType(), ExecInitNode(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, ExecSort(), makeNode, outerPlan, outerPlanState, PlanState::plan, ScanState::ps, PlanState::ps_ProjInfo, SortState::randomAccess, SO1_printf, SortState::sort_Done, SortState::ss, PlanState::state, TTSOpsMinimalTuple, TTSOpsVirtual, and SortState::tuplesortstate.

Referenced by ExecInitNode().

◆ ExecReScanSort()

void ExecReScanSort ( SortState node)

Definition at line 365 of file nodeSort.c.

366 {
368 
369  /*
370  * If we haven't sorted yet, just return. If outerplan's chgParam is not
371  * NULL then it will be re-scanned by ExecProcNode, else no reason to
372  * re-scan it at all.
373  */
374  if (!node->sort_Done)
375  return;
376 
377  /* must drop pointer to sort result tuple */
379 
380  /*
381  * If subnode is to be rescanned then we forget previous sort results; we
382  * have to re-read the subplan and re-sort. Also must re-sort if the
383  * bounded-sort parameters changed or we didn't select randomAccess.
384  *
385  * Otherwise we can just rewind and rescan the sorted output.
386  */
387  if (outerPlan->chgParam != NULL ||
388  node->bounded != node->bounded_Done ||
389  node->bound != node->bound_Done ||
390  !node->randomAccess)
391  {
392  node->sort_Done = false;
394  node->tuplesortstate = NULL;
395 
396  /*
397  * if chgParam of subnode is not null then plan will be re-scanned by
398  * first ExecProcNode.
399  */
400  if (outerPlan->chgParam == NULL)
402  }
403  else
405 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:78
int64 bound_Done
Definition: execnodes.h:2201
bool bounded_Done
Definition: execnodes.h:2200
int64 bound
Definition: execnodes.h:2198
void tuplesort_rescan(Tuplesortstate *state)
Definition: tuplesort.c:3379

References SortState::bound, SortState::bound_Done, SortState::bounded, SortState::bounded_Done, ExecClearTuple(), ExecReScan(), outerPlan, outerPlanState, ScanState::ps, PlanState::ps_ResultTupleSlot, SortState::randomAccess, SortState::sort_Done, SortState::ss, tuplesort_end(), tuplesort_rescan(), and SortState::tuplesortstate.

Referenced by ExecReScan().

◆ ExecSort()

static TupleTableSlot* ExecSort ( PlanState pstate)
static

Definition at line 50 of file nodeSort.c.

51 {
52  SortState *node = castNode(SortState, pstate);
53  EState *estate;
54  ScanDirection dir;
55  Tuplesortstate *tuplesortstate;
56  TupleTableSlot *slot;
57 
59 
60  /*
61  * get state info from node
62  */
63  SO1_printf("ExecSort: %s\n",
64  "entering routine");
65 
66  estate = node->ss.ps.state;
67  dir = estate->es_direction;
68  tuplesortstate = (Tuplesortstate *) node->tuplesortstate;
69 
70  /*
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.
73  */
74 
75  if (!node->sort_Done)
76  {
77  Sort *plannode = (Sort *) node->ss.ps.plan;
78  PlanState *outerNode;
79  TupleDesc tupDesc;
80  int tuplesortopts = TUPLESORT_NONE;
81 
82  SO1_printf("ExecSort: %s\n",
83  "sorting subplan");
84 
85  /*
86  * Want to scan subplan in the forward direction while creating the
87  * sorted data.
88  */
90 
91  /*
92  * Initialize tuplesort module.
93  */
94  SO1_printf("ExecSort: %s\n",
95  "calling tuplesort_begin");
96 
97  outerNode = outerPlanState(node);
98  tupDesc = ExecGetResultType(outerNode);
99 
100  if (node->randomAccess)
101  tuplesortopts |= TUPLESORT_RANDOMACCESS;
102  if (node->bounded)
103  tuplesortopts |= TUPLESORT_ALLOWBOUNDED;
104 
105  if (node->datumSort)
106  tuplesortstate = tuplesort_begin_datum(TupleDescAttr(tupDesc, 0)->atttypid,
107  plannode->sortOperators[0],
108  plannode->collations[0],
109  plannode->nullsFirst[0],
110  work_mem,
111  NULL,
112  tuplesortopts);
113  else
114  tuplesortstate = tuplesort_begin_heap(tupDesc,
115  plannode->numCols,
116  plannode->sortColIdx,
117  plannode->sortOperators,
118  plannode->collations,
119  plannode->nullsFirst,
120  work_mem,
121  NULL,
122  tuplesortopts);
123  if (node->bounded)
124  tuplesort_set_bound(tuplesortstate, node->bound);
125  node->tuplesortstate = (void *) tuplesortstate;
126 
127  /*
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.
130  */
131  if (node->datumSort)
132  {
133  for (;;)
134  {
135  slot = ExecProcNode(outerNode);
136 
137  if (TupIsNull(slot))
138  break;
139  slot_getsomeattrs(slot, 1);
140  tuplesort_putdatum(tuplesortstate,
141  slot->tts_values[0],
142  slot->tts_isnull[0]);
143  }
144  }
145  else
146  {
147  for (;;)
148  {
149  slot = ExecProcNode(outerNode);
150 
151  if (TupIsNull(slot))
152  break;
153  tuplesort_puttupleslot(tuplesortstate, slot);
154  }
155  }
156 
157  /*
158  * Complete the sort.
159  */
160  tuplesort_performsort(tuplesortstate);
161 
162  /*
163  * restore to user specified direction
164  */
165  estate->es_direction = dir;
166 
167  /*
168  * finally set the sorted flag to true
169  */
170  node->sort_Done = true;
171  node->bounded_Done = node->bounded;
172  node->bound_Done = node->bound;
173  if (node->shared_info && node->am_worker)
174  {
176 
178  Assert(ParallelWorkerNumber <= node->shared_info->num_workers);
180  tuplesort_get_stats(tuplesortstate, si);
181  }
182  SO1_printf("ExecSort: %s\n", "sorting done");
183  }
184 
185  SO1_printf("ExecSort: %s\n",
186  "retrieving tuple from tuplesort");
187 
188  slot = node->ss.ps.ps_ResultTupleSlot;
189 
190  /*
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.
196  */
197  if (node->datumSort)
198  {
199  ExecClearTuple(slot);
200  if (tuplesort_getdatum(tuplesortstate, ScanDirectionIsForward(dir),
201  &(slot->tts_values[0]), &(slot->tts_isnull[0]), NULL))
202  ExecStoreVirtualTuple(slot);
203  }
204  else
205  (void) tuplesort_gettupleslot(tuplesortstate,
207  false, slot, NULL);
208 
209  return slot;
210 }
int ParallelWorkerNumber
Definition: parallel.c:112
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1552
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:254
int work_mem
Definition: globals.c:125
#define IsParallelWorker()
Definition: parallel.h:61
Assert(fmt[strlen(fmt) - 1] !='\n')
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
ScanDirection
Definition: sdir.h:23
@ ForwardScanDirection
Definition: sdir.h:26
ScanDirection es_direction
Definition: execnodes.h:589
TuplesortInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:2186
bool am_worker
Definition: execnodes.h:2203
SharedSortInfo * shared_info
Definition: execnodes.h:2205
Oid * sortOperators
Definition: plannodes.h:850
int numCols
Definition: plannodes.h:848
bool * nullsFirst
Definition: plannodes.h:852
AttrNumber * sortColIdx
Definition: plannodes.h:849
Oid * collations
Definition: plannodes.h:851
bool * tts_isnull
Definition: tuptable.h:128
Datum * tts_values
Definition: tuptable.h:126
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:2196
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
Definition: tuplesort.c:1961
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Definition: tuplesort.c:1840
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, SortCoordinate coordinate, int sortopt)
Definition: tuplesort.c:1396
void tuplesort_get_stats(Tuplesortstate *state, TuplesortInstrumentation *stats)
Definition: tuplesort.c:3476
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy, TupleTableSlot *slot, Datum *abbrev)
Definition: tuplesort.c:2561
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2647
void tuplesort_set_bound(Tuplesortstate *state, int64 bound)
Definition: tuplesort.c:1484
Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, SortCoordinate coordinate, int sortopt)
Definition: tuplesort.c:1030
#define TUPLESORT_NONE
Definition: tuplesort.h:90
#define TUPLESORT_RANDOMACCESS
Definition: tuplesort.h:93
#define TUPLESORT_ALLOWBOUNDED
Definition: tuplesort.h:96
static void slot_getsomeattrs(TupleTableSlot *slot, int attnum)
Definition: tuptable.h:341
#define TupIsNull(slot)
Definition: tuptable.h:292

References SortState::am_worker, Assert(), SortState::bound, SortState::bound_Done, SortState::bounded, SortState::bounded_Done, castNode, CHECK_FOR_INTERRUPTS, Sort::collations, SortState::datumSort, EState::es_direction, ExecClearTuple(), ExecGetResultType(), ExecProcNode(), ExecStoreVirtualTuple(), ForwardScanDirection, if(), IsParallelWorker, Sort::nullsFirst, Sort::numCols, outerPlanState, ParallelWorkerNumber, PlanState::plan, ScanState::ps, PlanState::ps_ResultTupleSlot, SortState::randomAccess, ScanDirectionIsForward, SortState::shared_info, SharedSortInfo::sinstrument, slot_getsomeattrs(), SO1_printf, SortState::sort_Done, Sort::sortColIdx, Sort::sortOperators, SortState::ss, PlanState::state, TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TupIsNull, TupleDescAttr, TUPLESORT_ALLOWBOUNDED, tuplesort_begin_datum(), tuplesort_begin_heap(), tuplesort_get_stats(), tuplesort_getdatum(), tuplesort_gettupleslot(), TUPLESORT_NONE, tuplesort_performsort(), tuplesort_putdatum(), tuplesort_puttupleslot(), TUPLESORT_RANDOMACCESS, tuplesort_set_bound(), SortState::tuplesortstate, and work_mem.

Referenced by ExecInitSort().

◆ ExecSortEstimate()

void ExecSortEstimate ( SortState node,
ParallelContext pcxt 
)

Definition at line 419 of file nodeSort.c.

420 {
421  Size size;
422 
423  /* don't need this if not instrumenting or no workers */
424  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
425  return;
426 
427  size = mul_size(pcxt->nworkers, sizeof(TuplesortInstrumentation));
428  size = add_size(size, offsetof(SharedSortInfo, sinstrument));
429  shm_toc_estimate_chunk(&pcxt->estimator, size);
430  shm_toc_estimate_keys(&pcxt->estimator, 1);
431 }
#define offsetof(type, field)
Definition: c.h:727
size_t Size
Definition: c.h:540
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
shm_toc_estimator estimator
Definition: parallel.h:42
Instrumentation * instrument
Definition: execnodes.h:1008

References add_size(), ParallelContext::estimator, PlanState::instrument, mul_size(), ParallelContext::nworkers, offsetof, ScanState::ps, shm_toc_estimate_chunk, shm_toc_estimate_keys, and SortState::ss.

Referenced by ExecParallelEstimate().

◆ ExecSortInitializeDSM()

void ExecSortInitializeDSM ( SortState node,
ParallelContext pcxt 
)

Definition at line 440 of file nodeSort.c.

441 {
442  Size size;
443 
444  /* don't need this if not instrumenting or no workers */
445  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
446  return;
447 
448  size = offsetof(SharedSortInfo, sinstrument)
449  + pcxt->nworkers * sizeof(TuplesortInstrumentation);
450  node->shared_info = shm_toc_allocate(pcxt->toc, size);
451  /* ensure any unfilled slots will contain zeroes */
452  memset(node->shared_info, 0, size);
453  node->shared_info->num_workers = pcxt->nworkers;
454  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id,
455  node->shared_info);
456 }
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
shm_toc * toc
Definition: parallel.h:45
int plan_node_id
Definition: plannodes.h:141
struct TuplesortInstrumentation TuplesortInstrumentation

References PlanState::instrument, SharedSortInfo::num_workers, ParallelContext::nworkers, offsetof, PlanState::plan, Plan::plan_node_id, ScanState::ps, SortState::shared_info, shm_toc_allocate(), shm_toc_insert(), SortState::ss, and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

◆ ExecSortInitializeWorker()

void ExecSortInitializeWorker ( SortState node,
ParallelWorkerContext pwcxt 
)

Definition at line 465 of file nodeSort.c.

466 {
467  node->shared_info =
468  shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, true);
469  node->am_worker = true;
470 }
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

References SortState::am_worker, PlanState::plan, Plan::plan_node_id, ScanState::ps, SortState::shared_info, shm_toc_lookup(), SortState::ss, and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

◆ ExecSortMarkPos()

void ExecSortMarkPos ( SortState node)

Definition at line 332 of file nodeSort.c.

333 {
334  /*
335  * if we haven't sorted yet, just return
336  */
337  if (!node->sort_Done)
338  return;
339 
341 }
void tuplesort_markpos(Tuplesortstate *state)
Definition: tuplesort.c:3412

References SortState::sort_Done, tuplesort_markpos(), and SortState::tuplesortstate.

Referenced by ExecMarkPos().

◆ ExecSortRestrPos()

void ExecSortRestrPos ( SortState node)

Definition at line 350 of file nodeSort.c.

351 {
352  /*
353  * if we haven't sorted yet, just return.
354  */
355  if (!node->sort_Done)
356  return;
357 
358  /*
359  * restore the scan to the previously marked position
360  */
362 }
void tuplesort_restorepos(Tuplesortstate *state)
Definition: tuplesort.c:3443

References SortState::sort_Done, tuplesort_restorepos(), and SortState::tuplesortstate.

Referenced by ExecRestrPos().

◆ ExecSortRetrieveInstrumentation()

void ExecSortRetrieveInstrumentation ( SortState node)

Definition at line 479 of file nodeSort.c.

480 {
481  Size size;
482  SharedSortInfo *si;
483 
484  if (node->shared_info == NULL)
485  return;
486 
487  size = offsetof(SharedSortInfo, sinstrument)
489  si = palloc(size);
490  memcpy(si, node->shared_info, size);
491  node->shared_info = si;
492 }
void * palloc(Size size)
Definition: mcxt.c:1068

References SharedSortInfo::num_workers, offsetof, palloc(), and SortState::shared_info.

Referenced by ExecParallelRetrieveInstrumentation().