Header And Logo

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

nodeWorktablescan.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeWorktablescan.c
00004  *    routines to handle WorkTableScan 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/nodeWorktablescan.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #include "postgres.h"
00017 
00018 #include "executor/execdebug.h"
00019 #include "executor/nodeWorktablescan.h"
00020 
00021 static TupleTableSlot *WorkTableScanNext(WorkTableScanState *node);
00022 
00023 /* ----------------------------------------------------------------
00024  *      WorkTableScanNext
00025  *
00026  *      This is a workhorse for ExecWorkTableScan
00027  * ----------------------------------------------------------------
00028  */
00029 static TupleTableSlot *
00030 WorkTableScanNext(WorkTableScanState *node)
00031 {
00032     TupleTableSlot *slot;
00033     Tuplestorestate *tuplestorestate;
00034 
00035     /*
00036      * get information from the estate and scan state
00037      *
00038      * Note: we intentionally do not support backward scan.  Although it would
00039      * take only a couple more lines here, it would force nodeRecursiveunion.c
00040      * to create the tuplestore with backward scan enabled, which has a
00041      * performance cost.  In practice backward scan is never useful for a
00042      * worktable plan node, since it cannot appear high enough in the plan
00043      * tree of a scrollable cursor to be exposed to a backward-scan
00044      * requirement.  So it's not worth expending effort to support it.
00045      *
00046      * Note: we are also assuming that this node is the only reader of the
00047      * worktable.  Therefore, we don't need a private read pointer for the
00048      * tuplestore, nor do we need to tell tuplestore_gettupleslot to copy.
00049      */
00050     Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
00051 
00052     tuplestorestate = node->rustate->working_table;
00053 
00054     /*
00055      * Get the next tuple from tuplestore. Return NULL if no more tuples.
00056      */
00057     slot = node->ss.ss_ScanTupleSlot;
00058     (void) tuplestore_gettupleslot(tuplestorestate, true, false, slot);
00059     return slot;
00060 }
00061 
00062 /*
00063  * WorkTableScanRecheck -- access method routine to recheck a tuple in EvalPlanQual
00064  */
00065 static bool
00066 WorkTableScanRecheck(WorkTableScanState *node, TupleTableSlot *slot)
00067 {
00068     /* nothing to check */
00069     return true;
00070 }
00071 
00072 /* ----------------------------------------------------------------
00073  *      ExecWorkTableScan(node)
00074  *
00075  *      Scans the worktable sequentially and returns the next qualifying tuple.
00076  *      We call the ExecScan() routine and pass it the appropriate
00077  *      access method functions.
00078  * ----------------------------------------------------------------
00079  */
00080 TupleTableSlot *
00081 ExecWorkTableScan(WorkTableScanState *node)
00082 {
00083     /*
00084      * On the first call, find the ancestor RecursiveUnion's state via the
00085      * Param slot reserved for it.  (We can't do this during node init because
00086      * there are corner cases where we'll get the init call before the
00087      * RecursiveUnion does.)
00088      */
00089     if (node->rustate == NULL)
00090     {
00091         WorkTableScan *plan = (WorkTableScan *) node->ss.ps.plan;
00092         EState     *estate = node->ss.ps.state;
00093         ParamExecData *param;
00094 
00095         param = &(estate->es_param_exec_vals[plan->wtParam]);
00096         Assert(param->execPlan == NULL);
00097         Assert(!param->isnull);
00098         node->rustate = (RecursiveUnionState *) DatumGetPointer(param->value);
00099         Assert(node->rustate && IsA(node->rustate, RecursiveUnionState));
00100 
00101         /*
00102          * The scan tuple type (ie, the rowtype we expect to find in the work
00103          * table) is the same as the result rowtype of the ancestor
00104          * RecursiveUnion node.  Note this depends on the assumption that
00105          * RecursiveUnion doesn't allow projection.
00106          */
00107         ExecAssignScanType(&node->ss,
00108                            ExecGetResultType(&node->rustate->ps));
00109 
00110         /*
00111          * Now we can initialize the projection info.  This must be completed
00112          * before we can call ExecScan().
00113          */
00114         ExecAssignScanProjectionInfo(&node->ss);
00115     }
00116 
00117     return ExecScan(&node->ss,
00118                     (ExecScanAccessMtd) WorkTableScanNext,
00119                     (ExecScanRecheckMtd) WorkTableScanRecheck);
00120 }
00121 
00122 
00123 /* ----------------------------------------------------------------
00124  *      ExecInitWorkTableScan
00125  * ----------------------------------------------------------------
00126  */
00127 WorkTableScanState *
00128 ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
00129 {
00130     WorkTableScanState *scanstate;
00131 
00132     /* check for unsupported flags */
00133     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
00134 
00135     /*
00136      * WorkTableScan should not have any children.
00137      */
00138     Assert(outerPlan(node) == NULL);
00139     Assert(innerPlan(node) == NULL);
00140 
00141     /*
00142      * create new WorkTableScanState for node
00143      */
00144     scanstate = makeNode(WorkTableScanState);
00145     scanstate->ss.ps.plan = (Plan *) node;
00146     scanstate->ss.ps.state = estate;
00147     scanstate->rustate = NULL;  /* we'll set this later */
00148 
00149     /*
00150      * Miscellaneous initialization
00151      *
00152      * create expression context for node
00153      */
00154     ExecAssignExprContext(estate, &scanstate->ss.ps);
00155 
00156     /*
00157      * initialize child expressions
00158      */
00159     scanstate->ss.ps.targetlist = (List *)
00160         ExecInitExpr((Expr *) node->scan.plan.targetlist,
00161                      (PlanState *) scanstate);
00162     scanstate->ss.ps.qual = (List *)
00163         ExecInitExpr((Expr *) node->scan.plan.qual,
00164                      (PlanState *) scanstate);
00165 
00166     /*
00167      * tuple table initialization
00168      */
00169     ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
00170     ExecInitScanTupleSlot(estate, &scanstate->ss);
00171 
00172     /*
00173      * Initialize result tuple type, but not yet projection info.
00174      */
00175     ExecAssignResultTypeFromTL(&scanstate->ss.ps);
00176 
00177     scanstate->ss.ps.ps_TupFromTlist = false;
00178 
00179     return scanstate;
00180 }
00181 
00182 /* ----------------------------------------------------------------
00183  *      ExecEndWorkTableScan
00184  *
00185  *      frees any storage allocated through C routines.
00186  * ----------------------------------------------------------------
00187  */
00188 void
00189 ExecEndWorkTableScan(WorkTableScanState *node)
00190 {
00191     /*
00192      * Free exprcontext
00193      */
00194     ExecFreeExprContext(&node->ss.ps);
00195 
00196     /*
00197      * clean out the tuple table
00198      */
00199     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00200     ExecClearTuple(node->ss.ss_ScanTupleSlot);
00201 }
00202 
00203 /* ----------------------------------------------------------------
00204  *      ExecReScanWorkTableScan
00205  *
00206  *      Rescans the relation.
00207  * ----------------------------------------------------------------
00208  */
00209 void
00210 ExecReScanWorkTableScan(WorkTableScanState *node)
00211 {
00212     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00213 
00214     ExecScanReScan(&node->ss);
00215 
00216     /* No need (or way) to rescan if ExecWorkTableScan not called yet */
00217     if (node->rustate)
00218         tuplestore_rescan(node->rustate->working_table);
00219 }