1 /*-------------------------------------------------------------------------
4 * Routines to handle sorting of relations.
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.43 2003/05/05 17:57:47 tgl Exp $
13 *-------------------------------------------------------------------------
18 #include "executor/execdebug.h"
19 #include "executor/nodeSort.h"
20 #include "utils/tuplesort.h"
22 /* ----------------------------------------------------------------
25 * Extract the sorting key information from the plan node.
27 * Returns two palloc'd arrays, one of sort operator OIDs and
28 * one of attribute numbers.
29 * ----------------------------------------------------------------
32 ExtractSortKeys(Sort *sortnode,
43 * get information from the node
45 targetList = sortnode->plan.targetlist;
46 keycount = sortnode->keycount;
49 * first allocate space for results
52 elog(ERROR, "ExtractSortKeys: keycount <= 0");
53 sortOps = (Oid *) palloc0(keycount * sizeof(Oid));
54 *sortOperators = sortOps;
55 attNos = (AttrNumber *) palloc0(keycount * sizeof(AttrNumber));
59 * extract info from the resdom nodes in the target list
61 foreach(tl, targetList)
63 TargetEntry *target = (TargetEntry *) lfirst(tl);
64 Resdom *resdom = target->resdom;
65 Index reskey = resdom->reskey;
67 if (reskey > 0) /* ignore TLEs that are not sort keys */
69 Assert(reskey <= keycount);
70 sortOps[reskey - 1] = resdom->reskeyop;
71 attNos[reskey - 1] = resdom->resno;
76 /* ----------------------------------------------------------------
79 * Sorts tuples from the outer subtree of the node using tuplesort,
80 * which saves the results in a temporary file or memory. After the
81 * initial call, returns a tuple from the file with each call.
87 * -- the outer child is prepared to return the first tuple.
88 * ----------------------------------------------------------------
91 ExecSort(SortState *node)
95 Tuplesortstate *tuplesortstate;
101 * get state info from node
103 SO1_printf("ExecSort: %s\n",
106 estate = node->ss.ps.state;
107 dir = estate->es_direction;
108 tuplesortstate = (Tuplesortstate *) node->tuplesortstate;
111 * If first time through, read all tuples from outer plan and pass
112 * them to tuplesort.c. Subsequent calls just fetch tuples from
116 if (!node->sort_Done)
118 Sort *plannode = (Sort *) node->ss.ps.plan;
119 PlanState *outerNode;
124 SO1_printf("ExecSort: %s\n",
128 * Want to scan subplan in the forward direction while creating
131 estate->es_direction = ForwardScanDirection;
134 * Initialize tuplesort module.
136 SO1_printf("ExecSort: %s\n",
137 "calling tuplesort_begin");
139 outerNode = outerPlanState(node);
140 tupDesc = ExecGetResultType(outerNode);
142 ExtractSortKeys(plannode, &sortOperators, &attNums);
144 tuplesortstate = tuplesort_begin_heap(tupDesc, plannode->keycount,
145 sortOperators, attNums,
146 true /* randomAccess */ );
147 node->tuplesortstate = (void *) tuplesortstate;
149 pfree(sortOperators);
153 * Scan the subplan and feed all the tuples to tuplesort.
158 slot = ExecProcNode(outerNode);
163 tuplesort_puttuple(tuplesortstate, (void *) slot->val);
169 tuplesort_performsort(tuplesortstate);
172 * restore to user specified direction
174 estate->es_direction = dir;
177 * finally set the sorted flag to true
179 node->sort_Done = true;
180 SO1_printf("ExecSort: %s\n", "sorting done");
183 SO1_printf("ExecSort: %s\n",
184 "retrieving tuple from tuplesort");
187 * Get the first or next tuple from tuplesort. Returns NULL if no more
190 heapTuple = tuplesort_getheaptuple(tuplesortstate,
191 ScanDirectionIsForward(dir),
194 slot = node->ss.ps.ps_ResultTupleSlot;
195 return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
198 /* ----------------------------------------------------------------
201 * Creates the run-time state information for the sort node
202 * produced by the planner and initailizes its outer subtree.
203 * ----------------------------------------------------------------
206 ExecInitSort(Sort *node, EState *estate)
208 SortState *sortstate;
210 SO1_printf("ExecInitSort: %s\n",
211 "initializing sort node");
214 * create state structure
216 sortstate = makeNode(SortState);
217 sortstate->ss.ps.plan = (Plan *) node;
218 sortstate->ss.ps.state = estate;
220 sortstate->sort_Done = false;
221 sortstate->tuplesortstate = NULL;
224 * Miscellaneous initialization
226 * Sort nodes don't initialize their ExprContexts because they never call
227 * ExecQual or ExecProject.
230 #define SORT_NSLOTS 2
233 * tuple table initialization
235 * sort nodes only return scan tuples from their sorted relation.
237 ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
238 ExecInitScanTupleSlot(estate, &sortstate->ss);
241 * initializes child nodes
243 outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate);
246 * initialize tuple type. no need to initialize projection info
247 * because this node doesn't do projections.
249 ExecAssignResultTypeFromOuterPlan(&sortstate->ss.ps);
250 ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
251 sortstate->ss.ps.ps_ProjInfo = NULL;
253 SO1_printf("ExecInitSort: %s\n",
254 "sort node initialized");
260 ExecCountSlotsSort(Sort *node)
262 return ExecCountSlotsNode(outerPlan((Plan *) node)) +
263 ExecCountSlotsNode(innerPlan((Plan *) node)) +
267 /* ----------------------------------------------------------------
269 * ----------------------------------------------------------------
272 ExecEndSort(SortState *node)
274 SO1_printf("ExecEndSort: %s\n",
275 "shutting down sort node");
278 * clean out the tuple table
280 ExecClearTuple(node->ss.ss_ScanTupleSlot);
283 * Release tuplesort resources
285 if (node->tuplesortstate != NULL)
286 tuplesort_end((Tuplesortstate *) node->tuplesortstate);
287 node->tuplesortstate = NULL;
290 * shut down the subplan
292 ExecEndNode(outerPlanState(node));
294 SO1_printf("ExecEndSort: %s\n",
295 "sort node shutdown");
298 /* ----------------------------------------------------------------
301 * Calls tuplesort to save the current position in the sorted file.
302 * ----------------------------------------------------------------
305 ExecSortMarkPos(SortState *node)
308 * if we haven't sorted yet, just return
310 if (!node->sort_Done)
313 tuplesort_markpos((Tuplesortstate *) node->tuplesortstate);
316 /* ----------------------------------------------------------------
319 * Calls tuplesort to restore the last saved sort file position.
320 * ----------------------------------------------------------------
323 ExecSortRestrPos(SortState *node)
326 * if we haven't sorted yet, just return.
328 if (!node->sort_Done)
332 * restore the scan to the previously marked position
334 tuplesort_restorepos((Tuplesortstate *) node->tuplesortstate);
338 ExecReScanSort(SortState *node, ExprContext *exprCtxt)
341 * If we haven't sorted yet, just return. If outerplan' chgParam is
342 * not NULL then it will be re-scanned by ExecProcNode, else - no
343 * reason to re-scan it at all.
345 if (!node->sort_Done)
348 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
351 * If subnode is to be rescanned then we forget previous sort results;
352 * we have to re-read the subplan and re-sort.
354 * Otherwise we can just rewind and rescan the sorted output.
356 if (((PlanState *) node)->lefttree->chgParam != NULL)
358 node->sort_Done = false;
359 tuplesort_end((Tuplesortstate *) node->tuplesortstate);
360 node->tuplesortstate = NULL;
363 tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);