Header And Logo

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

nodeCtescan.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeCtescan.c
00004  *    routines to handle CteScan 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/nodeCtescan.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #include "postgres.h"
00017 
00018 #include "executor/execdebug.h"
00019 #include "executor/nodeCtescan.h"
00020 #include "miscadmin.h"
00021 
00022 static TupleTableSlot *CteScanNext(CteScanState *node);
00023 
00024 /* ----------------------------------------------------------------
00025  *      CteScanNext
00026  *
00027  *      This is a workhorse for ExecCteScan
00028  * ----------------------------------------------------------------
00029  */
00030 static TupleTableSlot *
00031 CteScanNext(CteScanState *node)
00032 {
00033     EState     *estate;
00034     ScanDirection dir;
00035     bool        forward;
00036     Tuplestorestate *tuplestorestate;
00037     bool        eof_tuplestore;
00038     TupleTableSlot *slot;
00039 
00040     /*
00041      * get state info from node
00042      */
00043     estate = node->ss.ps.state;
00044     dir = estate->es_direction;
00045     forward = ScanDirectionIsForward(dir);
00046     tuplestorestate = node->leader->cte_table;
00047     tuplestore_select_read_pointer(tuplestorestate, node->readptr);
00048     slot = node->ss.ss_ScanTupleSlot;
00049 
00050     /*
00051      * If we are not at the end of the tuplestore, or are going backwards, try
00052      * to fetch a tuple from tuplestore.
00053      */
00054     eof_tuplestore = tuplestore_ateof(tuplestorestate);
00055 
00056     if (!forward && eof_tuplestore)
00057     {
00058         if (!node->leader->eof_cte)
00059         {
00060             /*
00061              * When reversing direction at tuplestore EOF, the first
00062              * gettupleslot call will fetch the last-added tuple; but we want
00063              * to return the one before that, if possible. So do an extra
00064              * fetch.
00065              */
00066             if (!tuplestore_advance(tuplestorestate, forward))
00067                 return NULL;    /* the tuplestore must be empty */
00068         }
00069         eof_tuplestore = false;
00070     }
00071 
00072     /*
00073      * If we can fetch another tuple from the tuplestore, return it.
00074      *
00075      * Note: we have to use copy=true in the tuplestore_gettupleslot call,
00076      * because we are sharing the tuplestore with other nodes that might write
00077      * into the tuplestore before we get called again.
00078      */
00079     if (!eof_tuplestore)
00080     {
00081         if (tuplestore_gettupleslot(tuplestorestate, forward, true, slot))
00082             return slot;
00083         if (forward)
00084             eof_tuplestore = true;
00085     }
00086 
00087     /*
00088      * If necessary, try to fetch another row from the CTE query.
00089      *
00090      * Note: the eof_cte state variable exists to short-circuit further calls
00091      * of the CTE plan.  It's not optional, unfortunately, because some plan
00092      * node types are not robust about being called again when they've already
00093      * returned NULL.
00094      */
00095     if (eof_tuplestore && !node->leader->eof_cte)
00096     {
00097         TupleTableSlot *cteslot;
00098 
00099         /*
00100          * We can only get here with forward==true, so no need to worry about
00101          * which direction the subplan will go.
00102          */
00103         cteslot = ExecProcNode(node->cteplanstate);
00104         if (TupIsNull(cteslot))
00105         {
00106             node->leader->eof_cte = true;
00107             return NULL;
00108         }
00109 
00110         /*
00111          * Append a copy of the returned tuple to tuplestore.  NOTE: because
00112          * our read pointer is certainly in EOF state, its read position will
00113          * move forward over the added tuple.  This is what we want.  Also,
00114          * any other readers will *not* move past the new tuple, which is what
00115          * they want.
00116          */
00117         tuplestore_puttupleslot(tuplestorestate, cteslot);
00118 
00119         /*
00120          * We MUST copy the CTE query's output tuple into our own slot. This
00121          * is because other CteScan nodes might advance the CTE query before
00122          * we are called again, and our output tuple must stay stable over
00123          * that.
00124          */
00125         return ExecCopySlot(slot, cteslot);
00126     }
00127 
00128     /*
00129      * Nothing left ...
00130      */
00131     return ExecClearTuple(slot);
00132 }
00133 
00134 /*
00135  * CteScanRecheck -- access method routine to recheck a tuple in EvalPlanQual
00136  */
00137 static bool
00138 CteScanRecheck(CteScanState *node, TupleTableSlot *slot)
00139 {
00140     /* nothing to check */
00141     return true;
00142 }
00143 
00144 /* ----------------------------------------------------------------
00145  *      ExecCteScan(node)
00146  *
00147  *      Scans the CTE sequentially and returns the next qualifying tuple.
00148  *      We call the ExecScan() routine and pass it the appropriate
00149  *      access method functions.
00150  * ----------------------------------------------------------------
00151  */
00152 TupleTableSlot *
00153 ExecCteScan(CteScanState *node)
00154 {
00155     return ExecScan(&node->ss,
00156                     (ExecScanAccessMtd) CteScanNext,
00157                     (ExecScanRecheckMtd) CteScanRecheck);
00158 }
00159 
00160 
00161 /* ----------------------------------------------------------------
00162  *      ExecInitCteScan
00163  * ----------------------------------------------------------------
00164  */
00165 CteScanState *
00166 ExecInitCteScan(CteScan *node, EState *estate, int eflags)
00167 {
00168     CteScanState *scanstate;
00169     ParamExecData *prmdata;
00170 
00171     /* check for unsupported flags */
00172     Assert(!(eflags & EXEC_FLAG_MARK));
00173 
00174     /*
00175      * For the moment we have to force the tuplestore to allow REWIND, because
00176      * we might be asked to rescan the CTE even though upper levels didn't
00177      * tell us to be prepared to do it efficiently.  Annoying, since this
00178      * prevents truncation of the tuplestore.  XXX FIXME
00179      */
00180     eflags |= EXEC_FLAG_REWIND;
00181 
00182     /*
00183      * CteScan should not have any children.
00184      */
00185     Assert(outerPlan(node) == NULL);
00186     Assert(innerPlan(node) == NULL);
00187 
00188     /*
00189      * create new CteScanState for node
00190      */
00191     scanstate = makeNode(CteScanState);
00192     scanstate->ss.ps.plan = (Plan *) node;
00193     scanstate->ss.ps.state = estate;
00194     scanstate->eflags = eflags;
00195     scanstate->cte_table = NULL;
00196     scanstate->eof_cte = false;
00197 
00198     /*
00199      * Find the already-initialized plan for the CTE query.
00200      */
00201     scanstate->cteplanstate = (PlanState *) list_nth(estate->es_subplanstates,
00202                                                      node->ctePlanId - 1);
00203 
00204     /*
00205      * The Param slot associated with the CTE query is used to hold a pointer
00206      * to the CteState of the first CteScan node that initializes for this
00207      * CTE.  This node will be the one that holds the shared state for all the
00208      * CTEs, particularly the shared tuplestore.
00209      */
00210     prmdata = &(estate->es_param_exec_vals[node->cteParam]);
00211     Assert(prmdata->execPlan == NULL);
00212     Assert(!prmdata->isnull);
00213     scanstate->leader = (CteScanState *) DatumGetPointer(prmdata->value);
00214     if (scanstate->leader == NULL)
00215     {
00216         /* I am the leader */
00217         prmdata->value = PointerGetDatum(scanstate);
00218         scanstate->leader = scanstate;
00219         scanstate->cte_table = tuplestore_begin_heap(true, false, work_mem);
00220         tuplestore_set_eflags(scanstate->cte_table, scanstate->eflags);
00221         scanstate->readptr = 0;
00222     }
00223     else
00224     {
00225         /* Not the leader */
00226         Assert(IsA(scanstate->leader, CteScanState));
00227         scanstate->readptr =
00228             tuplestore_alloc_read_pointer(scanstate->leader->cte_table,
00229                                           scanstate->eflags);
00230     }
00231 
00232     /*
00233      * Miscellaneous initialization
00234      *
00235      * create expression context for node
00236      */
00237     ExecAssignExprContext(estate, &scanstate->ss.ps);
00238 
00239     /*
00240      * initialize child expressions
00241      */
00242     scanstate->ss.ps.targetlist = (List *)
00243         ExecInitExpr((Expr *) node->scan.plan.targetlist,
00244                      (PlanState *) scanstate);
00245     scanstate->ss.ps.qual = (List *)
00246         ExecInitExpr((Expr *) node->scan.plan.qual,
00247                      (PlanState *) scanstate);
00248 
00249     /*
00250      * tuple table initialization
00251      */
00252     ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
00253     ExecInitScanTupleSlot(estate, &scanstate->ss);
00254 
00255     /*
00256      * The scan tuple type (ie, the rowtype we expect to find in the work
00257      * table) is the same as the result rowtype of the CTE query.
00258      */
00259     ExecAssignScanType(&scanstate->ss,
00260                        ExecGetResultType(scanstate->cteplanstate));
00261 
00262     /*
00263      * Initialize result tuple type and projection info.
00264      */
00265     ExecAssignResultTypeFromTL(&scanstate->ss.ps);
00266     ExecAssignScanProjectionInfo(&scanstate->ss);
00267 
00268     scanstate->ss.ps.ps_TupFromTlist = false;
00269 
00270     return scanstate;
00271 }
00272 
00273 /* ----------------------------------------------------------------
00274  *      ExecEndCteScan
00275  *
00276  *      frees any storage allocated through C routines.
00277  * ----------------------------------------------------------------
00278  */
00279 void
00280 ExecEndCteScan(CteScanState *node)
00281 {
00282     /*
00283      * Free exprcontext
00284      */
00285     ExecFreeExprContext(&node->ss.ps);
00286 
00287     /*
00288      * clean out the tuple table
00289      */
00290     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00291     ExecClearTuple(node->ss.ss_ScanTupleSlot);
00292 
00293     /*
00294      * If I am the leader, free the tuplestore.
00295      */
00296     if (node->leader == node)
00297     {
00298         tuplestore_end(node->cte_table);
00299         node->cte_table = NULL;
00300     }
00301 }
00302 
00303 /* ----------------------------------------------------------------
00304  *      ExecReScanCteScan
00305  *
00306  *      Rescans the relation.
00307  * ----------------------------------------------------------------
00308  */
00309 void
00310 ExecReScanCteScan(CteScanState *node)
00311 {
00312     Tuplestorestate *tuplestorestate = node->leader->cte_table;
00313 
00314     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00315 
00316     ExecScanReScan(&node->ss);
00317 
00318     /*
00319      * Clear the tuplestore if a new scan of the underlying CTE is required.
00320      * This implicitly resets all the tuplestore's read pointers.  Note that
00321      * multiple CTE nodes might redundantly clear the tuplestore; that's OK,
00322      * and not unduly expensive.  We'll stop taking this path as soon as
00323      * somebody has attempted to read something from the underlying CTE
00324      * (thereby causing its chgParam to be cleared).
00325      */
00326     if (node->leader->cteplanstate->chgParam != NULL)
00327     {
00328         tuplestore_clear(tuplestorestate);
00329         node->leader->eof_cte = false;
00330     }
00331     else
00332     {
00333         /*
00334          * Else, just rewind my own pointer.  Either the underlying CTE
00335          * doesn't need a rescan (and we can re-read what's in the tuplestore
00336          * now), or somebody else already took care of it.
00337          */
00338         tuplestore_select_read_pointer(tuplestorestate, node->readptr);
00339         tuplestore_rescan(tuplestorestate);
00340     }
00341 }