Header And Logo

PostgreSQL
| The world's most advanced open source database.

nodeSort.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeSort.c
00004  *    Routines to handle sorting of relations.
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/executor/nodeSort.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #include "postgres.h"
00017 
00018 #include "executor/execdebug.h"
00019 #include "executor/nodeSort.h"
00020 #include "miscadmin.h"
00021 #include "utils/tuplesort.h"
00022 
00023 
00024 /* ----------------------------------------------------------------
00025  *      ExecSort
00026  *
00027  *      Sorts tuples from the outer subtree of the node using tuplesort,
00028  *      which saves the results in a temporary file or memory. After the
00029  *      initial call, returns a tuple from the file with each call.
00030  *
00031  *      Conditions:
00032  *        -- none.
00033  *
00034  *      Initial States:
00035  *        -- the outer child is prepared to return the first tuple.
00036  * ----------------------------------------------------------------
00037  */
00038 TupleTableSlot *
00039 ExecSort(SortState *node)
00040 {
00041     EState     *estate;
00042     ScanDirection dir;
00043     Tuplesortstate *tuplesortstate;
00044     TupleTableSlot *slot;
00045 
00046     /*
00047      * get state info from node
00048      */
00049     SO1_printf("ExecSort: %s\n",
00050                "entering routine");
00051 
00052     estate = node->ss.ps.state;
00053     dir = estate->es_direction;
00054     tuplesortstate = (Tuplesortstate *) node->tuplesortstate;
00055 
00056     /*
00057      * If first time through, read all tuples from outer plan and pass them to
00058      * tuplesort.c. Subsequent calls just fetch tuples from tuplesort.
00059      */
00060 
00061     if (!node->sort_Done)
00062     {
00063         Sort       *plannode = (Sort *) node->ss.ps.plan;
00064         PlanState  *outerNode;
00065         TupleDesc   tupDesc;
00066 
00067         SO1_printf("ExecSort: %s\n",
00068                    "sorting subplan");
00069 
00070         /*
00071          * Want to scan subplan in the forward direction while creating the
00072          * sorted data.
00073          */
00074         estate->es_direction = ForwardScanDirection;
00075 
00076         /*
00077          * Initialize tuplesort module.
00078          */
00079         SO1_printf("ExecSort: %s\n",
00080                    "calling tuplesort_begin");
00081 
00082         outerNode = outerPlanState(node);
00083         tupDesc = ExecGetResultType(outerNode);
00084 
00085         tuplesortstate = tuplesort_begin_heap(tupDesc,
00086                                               plannode->numCols,
00087                                               plannode->sortColIdx,
00088                                               plannode->sortOperators,
00089                                               plannode->collations,
00090                                               plannode->nullsFirst,
00091                                               work_mem,
00092                                               node->randomAccess);
00093         if (node->bounded)
00094             tuplesort_set_bound(tuplesortstate, node->bound);
00095         node->tuplesortstate = (void *) tuplesortstate;
00096 
00097         /*
00098          * Scan the subplan and feed all the tuples to tuplesort.
00099          */
00100 
00101         for (;;)
00102         {
00103             slot = ExecProcNode(outerNode);
00104 
00105             if (TupIsNull(slot))
00106                 break;
00107 
00108             tuplesort_puttupleslot(tuplesortstate, slot);
00109         }
00110 
00111         /*
00112          * Complete the sort.
00113          */
00114         tuplesort_performsort(tuplesortstate);
00115 
00116         /*
00117          * restore to user specified direction
00118          */
00119         estate->es_direction = dir;
00120 
00121         /*
00122          * finally set the sorted flag to true
00123          */
00124         node->sort_Done = true;
00125         node->bounded_Done = node->bounded;
00126         node->bound_Done = node->bound;
00127         SO1_printf("ExecSort: %s\n", "sorting done");
00128     }
00129 
00130     SO1_printf("ExecSort: %s\n",
00131                "retrieving tuple from tuplesort");
00132 
00133     /*
00134      * Get the first or next tuple from tuplesort. Returns NULL if no more
00135      * tuples.
00136      */
00137     slot = node->ss.ps.ps_ResultTupleSlot;
00138     (void) tuplesort_gettupleslot(tuplesortstate,
00139                                   ScanDirectionIsForward(dir),
00140                                   slot);
00141     return slot;
00142 }
00143 
00144 /* ----------------------------------------------------------------
00145  *      ExecInitSort
00146  *
00147  *      Creates the run-time state information for the sort node
00148  *      produced by the planner and initializes its outer subtree.
00149  * ----------------------------------------------------------------
00150  */
00151 SortState *
00152 ExecInitSort(Sort *node, EState *estate, int eflags)
00153 {
00154     SortState  *sortstate;
00155 
00156     SO1_printf("ExecInitSort: %s\n",
00157                "initializing sort node");
00158 
00159     /*
00160      * create state structure
00161      */
00162     sortstate = makeNode(SortState);
00163     sortstate->ss.ps.plan = (Plan *) node;
00164     sortstate->ss.ps.state = estate;
00165 
00166     /*
00167      * We must have random access to the sort output to do backward scan or
00168      * mark/restore.  We also prefer to materialize the sort output if we
00169      * might be called on to rewind and replay it many times.
00170      */
00171     sortstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
00172                                          EXEC_FLAG_BACKWARD |
00173                                          EXEC_FLAG_MARK)) != 0;
00174 
00175     sortstate->bounded = false;
00176     sortstate->sort_Done = false;
00177     sortstate->tuplesortstate = NULL;
00178 
00179     /*
00180      * Miscellaneous initialization
00181      *
00182      * Sort nodes don't initialize their ExprContexts because they never call
00183      * ExecQual or ExecProject.
00184      */
00185 
00186     /*
00187      * tuple table initialization
00188      *
00189      * sort nodes only return scan tuples from their sorted relation.
00190      */
00191     ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
00192     ExecInitScanTupleSlot(estate, &sortstate->ss);
00193 
00194     /*
00195      * initialize child nodes
00196      *
00197      * We shield the child node from the need to support REWIND, BACKWARD, or
00198      * MARK/RESTORE.
00199      */
00200     eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
00201 
00202     outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate, eflags);
00203 
00204     /*
00205      * initialize tuple type.  no need to initialize projection info because
00206      * this node doesn't do projections.
00207      */
00208     ExecAssignResultTypeFromTL(&sortstate->ss.ps);
00209     ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
00210     sortstate->ss.ps.ps_ProjInfo = NULL;
00211 
00212     SO1_printf("ExecInitSort: %s\n",
00213                "sort node initialized");
00214 
00215     return sortstate;
00216 }
00217 
00218 /* ----------------------------------------------------------------
00219  *      ExecEndSort(node)
00220  * ----------------------------------------------------------------
00221  */
00222 void
00223 ExecEndSort(SortState *node)
00224 {
00225     SO1_printf("ExecEndSort: %s\n",
00226                "shutting down sort node");
00227 
00228     /*
00229      * clean out the tuple table
00230      */
00231     ExecClearTuple(node->ss.ss_ScanTupleSlot);
00232     /* must drop pointer to sort result tuple */
00233     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00234 
00235     /*
00236      * Release tuplesort resources
00237      */
00238     if (node->tuplesortstate != NULL)
00239         tuplesort_end((Tuplesortstate *) node->tuplesortstate);
00240     node->tuplesortstate = NULL;
00241 
00242     /*
00243      * shut down the subplan
00244      */
00245     ExecEndNode(outerPlanState(node));
00246 
00247     SO1_printf("ExecEndSort: %s\n",
00248                "sort node shutdown");
00249 }
00250 
00251 /* ----------------------------------------------------------------
00252  *      ExecSortMarkPos
00253  *
00254  *      Calls tuplesort to save the current position in the sorted file.
00255  * ----------------------------------------------------------------
00256  */
00257 void
00258 ExecSortMarkPos(SortState *node)
00259 {
00260     /*
00261      * if we haven't sorted yet, just return
00262      */
00263     if (!node->sort_Done)
00264         return;
00265 
00266     tuplesort_markpos((Tuplesortstate *) node->tuplesortstate);
00267 }
00268 
00269 /* ----------------------------------------------------------------
00270  *      ExecSortRestrPos
00271  *
00272  *      Calls tuplesort to restore the last saved sort file position.
00273  * ----------------------------------------------------------------
00274  */
00275 void
00276 ExecSortRestrPos(SortState *node)
00277 {
00278     /*
00279      * if we haven't sorted yet, just return.
00280      */
00281     if (!node->sort_Done)
00282         return;
00283 
00284     /*
00285      * restore the scan to the previously marked position
00286      */
00287     tuplesort_restorepos((Tuplesortstate *) node->tuplesortstate);
00288 }
00289 
00290 void
00291 ExecReScanSort(SortState *node)
00292 {
00293     /*
00294      * If we haven't sorted yet, just return. If outerplan's chgParam is not
00295      * NULL then it will be re-scanned by ExecProcNode, else no reason to
00296      * re-scan it at all.
00297      */
00298     if (!node->sort_Done)
00299         return;
00300 
00301     /* must drop pointer to sort result tuple */
00302     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00303 
00304     /*
00305      * If subnode is to be rescanned then we forget previous sort results; we
00306      * have to re-read the subplan and re-sort.  Also must re-sort if the
00307      * bounded-sort parameters changed or we didn't select randomAccess.
00308      *
00309      * Otherwise we can just rewind and rescan the sorted output.
00310      */
00311     if (node->ss.ps.lefttree->chgParam != NULL ||
00312         node->bounded != node->bounded_Done ||
00313         node->bound != node->bound_Done ||
00314         !node->randomAccess)
00315     {
00316         node->sort_Done = false;
00317         tuplesort_end((Tuplesortstate *) node->tuplesortstate);
00318         node->tuplesortstate = NULL;
00319 
00320         /*
00321          * if chgParam of subnode is not null then plan will be re-scanned by
00322          * first ExecProcNode.
00323          */
00324         if (node->ss.ps.lefttree->chgParam == NULL)
00325             ExecReScan(node->ss.ps.lefttree);
00326     }
00327     else
00328         tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);
00329 }