Header And Logo

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

nodeMaterial.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeMaterial.c
00004  *    Routines to handle materialization nodes.
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/nodeMaterial.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 /*
00016  * INTERFACE ROUTINES
00017  *      ExecMaterial            - materialize the result of a subplan
00018  *      ExecInitMaterial        - initialize node and subnodes
00019  *      ExecEndMaterial         - shutdown node and subnodes
00020  *
00021  */
00022 #include "postgres.h"
00023 
00024 #include "executor/executor.h"
00025 #include "executor/nodeMaterial.h"
00026 #include "miscadmin.h"
00027 
00028 /* ----------------------------------------------------------------
00029  *      ExecMaterial
00030  *
00031  *      As long as we are at the end of the data collected in the tuplestore,
00032  *      we collect one new row from the subplan on each call, and stash it
00033  *      aside in the tuplestore before returning it.  The tuplestore is
00034  *      only read if we are asked to scan backwards, rescan, or mark/restore.
00035  *
00036  * ----------------------------------------------------------------
00037  */
00038 TupleTableSlot *                /* result tuple from subplan */
00039 ExecMaterial(MaterialState *node)
00040 {
00041     EState     *estate;
00042     ScanDirection dir;
00043     bool        forward;
00044     Tuplestorestate *tuplestorestate;
00045     bool        eof_tuplestore;
00046     TupleTableSlot *slot;
00047 
00048     /*
00049      * get state info from node
00050      */
00051     estate = node->ss.ps.state;
00052     dir = estate->es_direction;
00053     forward = ScanDirectionIsForward(dir);
00054     tuplestorestate = node->tuplestorestate;
00055 
00056     /*
00057      * If first time through, and we need a tuplestore, initialize it.
00058      */
00059     if (tuplestorestate == NULL && node->eflags != 0)
00060     {
00061         tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
00062         tuplestore_set_eflags(tuplestorestate, node->eflags);
00063         if (node->eflags & EXEC_FLAG_MARK)
00064         {
00065             /*
00066              * Allocate a second read pointer to serve as the mark. We know it
00067              * must have index 1, so needn't store that.
00068              */
00069             int ptrno   PG_USED_FOR_ASSERTS_ONLY;
00070 
00071             ptrno = tuplestore_alloc_read_pointer(tuplestorestate,
00072                                                   node->eflags);
00073             Assert(ptrno == 1);
00074         }
00075         node->tuplestorestate = tuplestorestate;
00076     }
00077 
00078     /*
00079      * If we are not at the end of the tuplestore, or are going backwards, try
00080      * to fetch a tuple from tuplestore.
00081      */
00082     eof_tuplestore = (tuplestorestate == NULL) ||
00083         tuplestore_ateof(tuplestorestate);
00084 
00085     if (!forward && eof_tuplestore)
00086     {
00087         if (!node->eof_underlying)
00088         {
00089             /*
00090              * When reversing direction at tuplestore EOF, the first
00091              * gettupleslot call will fetch the last-added tuple; but we want
00092              * to return the one before that, if possible. So do an extra
00093              * fetch.
00094              */
00095             if (!tuplestore_advance(tuplestorestate, forward))
00096                 return NULL;    /* the tuplestore must be empty */
00097         }
00098         eof_tuplestore = false;
00099     }
00100 
00101     /*
00102      * If we can fetch another tuple from the tuplestore, return it.
00103      */
00104     slot = node->ss.ps.ps_ResultTupleSlot;
00105     if (!eof_tuplestore)
00106     {
00107         if (tuplestore_gettupleslot(tuplestorestate, forward, false, slot))
00108             return slot;
00109         if (forward)
00110             eof_tuplestore = true;
00111     }
00112 
00113     /*
00114      * If necessary, try to fetch another row from the subplan.
00115      *
00116      * Note: the eof_underlying state variable exists to short-circuit further
00117      * subplan calls.  It's not optional, unfortunately, because some plan
00118      * node types are not robust about being called again when they've already
00119      * returned NULL.
00120      */
00121     if (eof_tuplestore && !node->eof_underlying)
00122     {
00123         PlanState  *outerNode;
00124         TupleTableSlot *outerslot;
00125 
00126         /*
00127          * We can only get here with forward==true, so no need to worry about
00128          * which direction the subplan will go.
00129          */
00130         outerNode = outerPlanState(node);
00131         outerslot = ExecProcNode(outerNode);
00132         if (TupIsNull(outerslot))
00133         {
00134             node->eof_underlying = true;
00135             return NULL;
00136         }
00137 
00138         /*
00139          * Append a copy of the returned tuple to tuplestore.  NOTE: because
00140          * the tuplestore is certainly in EOF state, its read position will
00141          * move forward over the added tuple.  This is what we want.
00142          */
00143         if (tuplestorestate)
00144             tuplestore_puttupleslot(tuplestorestate, outerslot);
00145 
00146         /*
00147          * We can just return the subplan's returned tuple, without copying.
00148          */
00149         return outerslot;
00150     }
00151 
00152     /*
00153      * Nothing left ...
00154      */
00155     return ExecClearTuple(slot);
00156 }
00157 
00158 /* ----------------------------------------------------------------
00159  *      ExecInitMaterial
00160  * ----------------------------------------------------------------
00161  */
00162 MaterialState *
00163 ExecInitMaterial(Material *node, EState *estate, int eflags)
00164 {
00165     MaterialState *matstate;
00166     Plan       *outerPlan;
00167 
00168     /*
00169      * create state structure
00170      */
00171     matstate = makeNode(MaterialState);
00172     matstate->ss.ps.plan = (Plan *) node;
00173     matstate->ss.ps.state = estate;
00174 
00175     /*
00176      * We must have a tuplestore buffering the subplan output to do backward
00177      * scan or mark/restore.  We also prefer to materialize the subplan output
00178      * if we might be called on to rewind and replay it many times. However,
00179      * if none of these cases apply, we can skip storing the data.
00180      */
00181     matstate->eflags = (eflags & (EXEC_FLAG_REWIND |
00182                                   EXEC_FLAG_BACKWARD |
00183                                   EXEC_FLAG_MARK));
00184 
00185     /*
00186      * Tuplestore's interpretation of the flag bits is subtly different from
00187      * the general executor meaning: it doesn't think BACKWARD necessarily
00188      * means "backwards all the way to start".  If told to support BACKWARD we
00189      * must include REWIND in the tuplestore eflags, else tuplestore_trim
00190      * might throw away too much.
00191      */
00192     if (eflags & EXEC_FLAG_BACKWARD)
00193         matstate->eflags |= EXEC_FLAG_REWIND;
00194 
00195     matstate->eof_underlying = false;
00196     matstate->tuplestorestate = NULL;
00197 
00198     /*
00199      * Miscellaneous initialization
00200      *
00201      * Materialization nodes don't need ExprContexts because they never call
00202      * ExecQual or ExecProject.
00203      */
00204 
00205     /*
00206      * tuple table initialization
00207      *
00208      * material nodes only return tuples from their materialized relation.
00209      */
00210     ExecInitResultTupleSlot(estate, &matstate->ss.ps);
00211     ExecInitScanTupleSlot(estate, &matstate->ss);
00212 
00213     /*
00214      * initialize child nodes
00215      *
00216      * We shield the child node from the need to support REWIND, BACKWARD, or
00217      * MARK/RESTORE.
00218      */
00219     eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
00220 
00221     outerPlan = outerPlan(node);
00222     outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags);
00223 
00224     /*
00225      * initialize tuple type.  no need to initialize projection info because
00226      * this node doesn't do projections.
00227      */
00228     ExecAssignResultTypeFromTL(&matstate->ss.ps);
00229     ExecAssignScanTypeFromOuterPlan(&matstate->ss);
00230     matstate->ss.ps.ps_ProjInfo = NULL;
00231 
00232     return matstate;
00233 }
00234 
00235 /* ----------------------------------------------------------------
00236  *      ExecEndMaterial
00237  * ----------------------------------------------------------------
00238  */
00239 void
00240 ExecEndMaterial(MaterialState *node)
00241 {
00242     /*
00243      * clean out the tuple table
00244      */
00245     ExecClearTuple(node->ss.ss_ScanTupleSlot);
00246 
00247     /*
00248      * Release tuplestore resources
00249      */
00250     if (node->tuplestorestate != NULL)
00251         tuplestore_end(node->tuplestorestate);
00252     node->tuplestorestate = NULL;
00253 
00254     /*
00255      * shut down the subplan
00256      */
00257     ExecEndNode(outerPlanState(node));
00258 }
00259 
00260 /* ----------------------------------------------------------------
00261  *      ExecMaterialMarkPos
00262  *
00263  *      Calls tuplestore to save the current position in the stored file.
00264  * ----------------------------------------------------------------
00265  */
00266 void
00267 ExecMaterialMarkPos(MaterialState *node)
00268 {
00269     Assert(node->eflags & EXEC_FLAG_MARK);
00270 
00271     /*
00272      * if we haven't materialized yet, just return.
00273      */
00274     if (!node->tuplestorestate)
00275         return;
00276 
00277     /*
00278      * copy the active read pointer to the mark.
00279      */
00280     tuplestore_copy_read_pointer(node->tuplestorestate, 0, 1);
00281 
00282     /*
00283      * since we may have advanced the mark, try to truncate the tuplestore.
00284      */
00285     tuplestore_trim(node->tuplestorestate);
00286 }
00287 
00288 /* ----------------------------------------------------------------
00289  *      ExecMaterialRestrPos
00290  *
00291  *      Calls tuplestore to restore the last saved file position.
00292  * ----------------------------------------------------------------
00293  */
00294 void
00295 ExecMaterialRestrPos(MaterialState *node)
00296 {
00297     Assert(node->eflags & EXEC_FLAG_MARK);
00298 
00299     /*
00300      * if we haven't materialized yet, just return.
00301      */
00302     if (!node->tuplestorestate)
00303         return;
00304 
00305     /*
00306      * copy the mark to the active read pointer.
00307      */
00308     tuplestore_copy_read_pointer(node->tuplestorestate, 1, 0);
00309 }
00310 
00311 /* ----------------------------------------------------------------
00312  *      ExecReScanMaterial
00313  *
00314  *      Rescans the materialized relation.
00315  * ----------------------------------------------------------------
00316  */
00317 void
00318 ExecReScanMaterial(MaterialState *node)
00319 {
00320     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00321 
00322     if (node->eflags != 0)
00323     {
00324         /*
00325          * If we haven't materialized yet, just return. If outerplan's
00326          * chgParam is not NULL then it will be re-scanned by ExecProcNode,
00327          * else no reason to re-scan it at all.
00328          */
00329         if (!node->tuplestorestate)
00330             return;
00331 
00332         /*
00333          * If subnode is to be rescanned then we forget previous stored
00334          * results; we have to re-read the subplan and re-store.  Also, if we
00335          * told tuplestore it needn't support rescan, we lose and must
00336          * re-read.  (This last should not happen in common cases; else our
00337          * caller lied by not passing EXEC_FLAG_REWIND to us.)
00338          *
00339          * Otherwise we can just rewind and rescan the stored output. The
00340          * state of the subnode does not change.
00341          */
00342         if (node->ss.ps.lefttree->chgParam != NULL ||
00343             (node->eflags & EXEC_FLAG_REWIND) == 0)
00344         {
00345             tuplestore_end(node->tuplestorestate);
00346             node->tuplestorestate = NULL;
00347             if (node->ss.ps.lefttree->chgParam == NULL)
00348                 ExecReScan(node->ss.ps.lefttree);
00349             node->eof_underlying = false;
00350         }
00351         else
00352             tuplestore_rescan(node->tuplestorestate);
00353     }
00354     else
00355     {
00356         /* In this case we are just passing on the subquery's output */
00357 
00358         /*
00359          * if chgParam of subnode is not null then plan will be re-scanned by
00360          * first ExecProcNode.
00361          */
00362         if (node->ss.ps.lefttree->chgParam == NULL)
00363             ExecReScan(node->ss.ps.lefttree);
00364         node->eof_underlying = false;
00365     }
00366 }