1 /*-------------------------------------------------------------------------
4 * Routines to handle sorting of relations.
6 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeSort.c
13 *-------------------------------------------------------------------------
18 #include "executor/execdebug.h"
19 #include "executor/nodeSort.h"
20 #include "miscadmin.h"
21 #include "utils/tuplesort.h"
24 /* ----------------------------------------------------------------
27 * Sorts tuples from the outer subtree of the node using tuplesort,
28 * which saves the results in a temporary file or memory. After the
29 * initial call, returns a tuple from the file with each call.
35 * -- the outer child is prepared to return the first tuple.
36 * ----------------------------------------------------------------
39 ExecSort(SortState *node)
43 Tuplesortstate *tuplesortstate;
47 * get state info from node
49 SO1_printf("ExecSort: %s\n",
52 estate = node->ss.ps.state;
53 dir = estate->es_direction;
54 tuplesortstate = (Tuplesortstate *) node->tuplesortstate;
57 * If first time through, read all tuples from outer plan and pass them to
58 * tuplesort.c. Subsequent calls just fetch tuples from tuplesort.
63 Sort *plannode = (Sort *) node->ss.ps.plan;
67 SO1_printf("ExecSort: %s\n",
71 * Want to scan subplan in the forward direction while creating the
74 estate->es_direction = ForwardScanDirection;
77 * Initialize tuplesort module.
79 SO1_printf("ExecSort: %s\n",
80 "calling tuplesort_begin");
82 outerNode = outerPlanState(node);
83 tupDesc = ExecGetResultType(outerNode);
85 tuplesortstate = tuplesort_begin_heap(tupDesc,
88 plannode->sortOperators,
94 tuplesort_set_bound(tuplesortstate, node->bound);
95 node->tuplesortstate = (void *) tuplesortstate;
98 * Scan the subplan and feed all the tuples to tuplesort.
103 slot = ExecProcNode(outerNode);
108 tuplesort_puttupleslot(tuplesortstate, slot);
114 tuplesort_performsort(tuplesortstate);
117 * restore to user specified direction
119 estate->es_direction = dir;
122 * finally set the sorted flag to true
124 node->sort_Done = true;
125 node->bounded_Done = node->bounded;
126 node->bound_Done = node->bound;
127 SO1_printf("ExecSort: %s\n", "sorting done");
130 SO1_printf("ExecSort: %s\n",
131 "retrieving tuple from tuplesort");
134 * Get the first or next tuple from tuplesort. Returns NULL if no more
137 slot = node->ss.ps.ps_ResultTupleSlot;
138 (void) tuplesort_gettupleslot(tuplesortstate,
139 ScanDirectionIsForward(dir),
144 /* ----------------------------------------------------------------
147 * Creates the run-time state information for the sort node
148 * produced by the planner and initializes its outer subtree.
149 * ----------------------------------------------------------------
152 ExecInitSort(Sort *node, EState *estate, int eflags)
154 SortState *sortstate;
156 SO1_printf("ExecInitSort: %s\n",
157 "initializing sort node");
160 * create state structure
162 sortstate = makeNode(SortState);
163 sortstate->ss.ps.plan = (Plan *) node;
164 sortstate->ss.ps.state = estate;
167 * We must have random access to the sort output to do backward scan or
168 * mark/restore. We also prefer to materialize the sort output if we
169 * might be called on to rewind and replay it many times.
171 sortstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
173 EXEC_FLAG_MARK)) != 0;
175 sortstate->bounded = false;
176 sortstate->sort_Done = false;
177 sortstate->tuplesortstate = NULL;
180 * Miscellaneous initialization
182 * Sort nodes don't initialize their ExprContexts because they never call
183 * ExecQual or ExecProject.
187 * tuple table initialization
189 * sort nodes only return scan tuples from their sorted relation.
191 ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
192 ExecInitScanTupleSlot(estate, &sortstate->ss);
195 * initialize child nodes
197 * We shield the child node from the need to support REWIND, BACKWARD, or
200 eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
202 outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate, eflags);
205 * initialize tuple type. no need to initialize projection info because
206 * this node doesn't do projections.
208 ExecAssignResultTypeFromTL(&sortstate->ss.ps);
209 ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
210 sortstate->ss.ps.ps_ProjInfo = NULL;
212 SO1_printf("ExecInitSort: %s\n",
213 "sort node initialized");
218 /* ----------------------------------------------------------------
220 * ----------------------------------------------------------------
223 ExecEndSort(SortState *node)
225 SO1_printf("ExecEndSort: %s\n",
226 "shutting down sort node");
229 * clean out the tuple table
231 ExecClearTuple(node->ss.ss_ScanTupleSlot);
232 /* must drop pointer to sort result tuple */
233 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
236 * Release tuplesort resources
238 if (node->tuplesortstate != NULL)
239 tuplesort_end((Tuplesortstate *) node->tuplesortstate);
240 node->tuplesortstate = NULL;
243 * shut down the subplan
245 ExecEndNode(outerPlanState(node));
247 SO1_printf("ExecEndSort: %s\n",
248 "sort node shutdown");
251 /* ----------------------------------------------------------------
254 * Calls tuplesort to save the current position in the sorted file.
255 * ----------------------------------------------------------------
258 ExecSortMarkPos(SortState *node)
261 * if we haven't sorted yet, just return
263 if (!node->sort_Done)
266 tuplesort_markpos((Tuplesortstate *) node->tuplesortstate);
269 /* ----------------------------------------------------------------
272 * Calls tuplesort to restore the last saved sort file position.
273 * ----------------------------------------------------------------
276 ExecSortRestrPos(SortState *node)
279 * if we haven't sorted yet, just return.
281 if (!node->sort_Done)
285 * restore the scan to the previously marked position
287 tuplesort_restorepos((Tuplesortstate *) node->tuplesortstate);
291 ExecReScanSort(SortState *node)
294 * If we haven't sorted yet, just return. If outerplan's chgParam is not
295 * NULL then it will be re-scanned by ExecProcNode, else no reason to
298 if (!node->sort_Done)
301 /* must drop pointer to sort result tuple */
302 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
305 * If subnode is to be rescanned then we forget previous sort results; we
306 * have to re-read the subplan and re-sort. Also must re-sort if the
307 * bounded-sort parameters changed or we didn't select randomAccess.
309 * Otherwise we can just rewind and rescan the sorted output.
311 if (node->ss.ps.lefttree->chgParam != NULL ||
312 node->bounded != node->bounded_Done ||
313 node->bound != node->bound_Done ||
316 node->sort_Done = false;
317 tuplesort_end((Tuplesortstate *) node->tuplesortstate);
318 node->tuplesortstate = NULL;
321 * if chgParam of subnode is not null then plan will be re-scanned by
322 * first ExecProcNode.
324 if (node->ss.ps.lefttree->chgParam == NULL)
325 ExecReScan(node->ss.ps.lefttree);
328 tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);