Header And Logo

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

nodeValuesscan.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeValuesscan.c
00004  *    Support routines for scanning Values lists
00005  *    ("VALUES (...), (...), ..." in rangetable).
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  * Portions Copyright (c) 1994, Regents of the University of California
00009  *
00010  *
00011  * IDENTIFICATION
00012  *    src/backend/executor/nodeValuesscan.c
00013  *
00014  *-------------------------------------------------------------------------
00015  */
00016 /*
00017  * INTERFACE ROUTINES
00018  *      ExecValuesScan          scans a values list.
00019  *      ExecValuesNext          retrieve next tuple in sequential order.
00020  *      ExecInitValuesScan      creates and initializes a valuesscan node.
00021  *      ExecEndValuesScan       releases any storage allocated.
00022  *      ExecReScanValuesScan    rescans the values list
00023  */
00024 #include "postgres.h"
00025 
00026 #include "executor/executor.h"
00027 #include "executor/nodeValuesscan.h"
00028 #include "parser/parsetree.h"
00029 
00030 
00031 static TupleTableSlot *ValuesNext(ValuesScanState *node);
00032 
00033 
00034 /* ----------------------------------------------------------------
00035  *                      Scan Support
00036  * ----------------------------------------------------------------
00037  */
00038 
00039 /* ----------------------------------------------------------------
00040  *      ValuesNext
00041  *
00042  *      This is a workhorse for ExecValuesScan
00043  * ----------------------------------------------------------------
00044  */
00045 static TupleTableSlot *
00046 ValuesNext(ValuesScanState *node)
00047 {
00048     TupleTableSlot *slot;
00049     EState     *estate;
00050     ExprContext *econtext;
00051     ScanDirection direction;
00052     List       *exprlist;
00053 
00054     /*
00055      * get information from the estate and scan state
00056      */
00057     estate = node->ss.ps.state;
00058     direction = estate->es_direction;
00059     slot = node->ss.ss_ScanTupleSlot;
00060     econtext = node->rowcontext;
00061 
00062     /*
00063      * Get the next tuple. Return NULL if no more tuples.
00064      */
00065     if (ScanDirectionIsForward(direction))
00066     {
00067         if (node->curr_idx < node->array_len)
00068             node->curr_idx++;
00069         if (node->curr_idx < node->array_len)
00070             exprlist = node->exprlists[node->curr_idx];
00071         else
00072             exprlist = NIL;
00073     }
00074     else
00075     {
00076         if (node->curr_idx >= 0)
00077             node->curr_idx--;
00078         if (node->curr_idx >= 0)
00079             exprlist = node->exprlists[node->curr_idx];
00080         else
00081             exprlist = NIL;
00082     }
00083 
00084     /*
00085      * Always clear the result slot; this is appropriate if we are at the end
00086      * of the data, and if we're not, we still need it as the first step of
00087      * the store-virtual-tuple protocol.  It seems wise to clear the slot
00088      * before we reset the context it might have pointers into.
00089      */
00090     ExecClearTuple(slot);
00091 
00092     if (exprlist)
00093     {
00094         MemoryContext oldContext;
00095         List       *exprstatelist;
00096         Datum      *values;
00097         bool       *isnull;
00098         ListCell   *lc;
00099         int         resind;
00100 
00101         /*
00102          * Get rid of any prior cycle's leftovers.  We use ReScanExprContext
00103          * not just ResetExprContext because we want any registered shutdown
00104          * callbacks to be called.
00105          */
00106         ReScanExprContext(econtext);
00107 
00108         /*
00109          * Build the expression eval state in the econtext's per-tuple memory.
00110          * This is a tad unusual, but we want to delete the eval state again
00111          * when we move to the next row, to avoid growth of memory
00112          * requirements over a long values list.
00113          */
00114         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
00115 
00116         /*
00117          * Pass NULL, not my plan node, because we don't want anything in this
00118          * transient state linking into permanent state.  The only possibility
00119          * is a SubPlan, and there shouldn't be any (any subselects in the
00120          * VALUES list should be InitPlans).
00121          */
00122         exprstatelist = (List *) ExecInitExpr((Expr *) exprlist, NULL);
00123 
00124         /* parser should have checked all sublists are the same length */
00125         Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
00126 
00127         /*
00128          * Compute the expressions and build a virtual result tuple. We
00129          * already did ExecClearTuple(slot).
00130          */
00131         values = slot->tts_values;
00132         isnull = slot->tts_isnull;
00133 
00134         resind = 0;
00135         foreach(lc, exprstatelist)
00136         {
00137             ExprState  *estate = (ExprState *) lfirst(lc);
00138 
00139             values[resind] = ExecEvalExpr(estate,
00140                                           econtext,
00141                                           &isnull[resind],
00142                                           NULL);
00143             resind++;
00144         }
00145 
00146         MemoryContextSwitchTo(oldContext);
00147 
00148         /*
00149          * And return the virtual tuple.
00150          */
00151         ExecStoreVirtualTuple(slot);
00152     }
00153 
00154     return slot;
00155 }
00156 
00157 /*
00158  * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
00159  */
00160 static bool
00161 ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
00162 {
00163     /* nothing to check */
00164     return true;
00165 }
00166 
00167 /* ----------------------------------------------------------------
00168  *      ExecValuesScan(node)
00169  *
00170  *      Scans the values lists sequentially and returns the next qualifying
00171  *      tuple.
00172  *      We call the ExecScan() routine and pass it the appropriate
00173  *      access method functions.
00174  * ----------------------------------------------------------------
00175  */
00176 TupleTableSlot *
00177 ExecValuesScan(ValuesScanState *node)
00178 {
00179     return ExecScan(&node->ss,
00180                     (ExecScanAccessMtd) ValuesNext,
00181                     (ExecScanRecheckMtd) ValuesRecheck);
00182 }
00183 
00184 /* ----------------------------------------------------------------
00185  *      ExecInitValuesScan
00186  * ----------------------------------------------------------------
00187  */
00188 ValuesScanState *
00189 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
00190 {
00191     ValuesScanState *scanstate;
00192     RangeTblEntry *rte = rt_fetch(node->scan.scanrelid,
00193                                   estate->es_range_table);
00194     TupleDesc   tupdesc;
00195     ListCell   *vtl;
00196     int         i;
00197     PlanState  *planstate;
00198 
00199     /*
00200      * ValuesScan should not have any children.
00201      */
00202     Assert(outerPlan(node) == NULL);
00203     Assert(innerPlan(node) == NULL);
00204 
00205     /*
00206      * create new ScanState for node
00207      */
00208     scanstate = makeNode(ValuesScanState);
00209     scanstate->ss.ps.plan = (Plan *) node;
00210     scanstate->ss.ps.state = estate;
00211 
00212     /*
00213      * Miscellaneous initialization
00214      */
00215     planstate = &scanstate->ss.ps;
00216 
00217     /*
00218      * Create expression contexts.  We need two, one for per-sublist
00219      * processing and one for execScan.c to use for quals and projections. We
00220      * cheat a little by using ExecAssignExprContext() to build both.
00221      */
00222     ExecAssignExprContext(estate, planstate);
00223     scanstate->rowcontext = planstate->ps_ExprContext;
00224     ExecAssignExprContext(estate, planstate);
00225 
00226     /*
00227      * tuple table initialization
00228      */
00229     ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
00230     ExecInitScanTupleSlot(estate, &scanstate->ss);
00231 
00232     /*
00233      * initialize child expressions
00234      */
00235     scanstate->ss.ps.targetlist = (List *)
00236         ExecInitExpr((Expr *) node->scan.plan.targetlist,
00237                      (PlanState *) scanstate);
00238     scanstate->ss.ps.qual = (List *)
00239         ExecInitExpr((Expr *) node->scan.plan.qual,
00240                      (PlanState *) scanstate);
00241 
00242     /*
00243      * get info about values list
00244      */
00245     tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists),
00246                                    rte->eref->colnames);
00247 
00248     ExecAssignScanType(&scanstate->ss, tupdesc);
00249 
00250     /*
00251      * Other node-specific setup
00252      */
00253     scanstate->marked_idx = -1;
00254     scanstate->curr_idx = -1;
00255     scanstate->array_len = list_length(node->values_lists);
00256 
00257     /* convert list of sublists into array of sublists for easy addressing */
00258     scanstate->exprlists = (List **)
00259         palloc(scanstate->array_len * sizeof(List *));
00260     i = 0;
00261     foreach(vtl, node->values_lists)
00262     {
00263         scanstate->exprlists[i++] = (List *) lfirst(vtl);
00264     }
00265 
00266     scanstate->ss.ps.ps_TupFromTlist = false;
00267 
00268     /*
00269      * Initialize result tuple type and projection info.
00270      */
00271     ExecAssignResultTypeFromTL(&scanstate->ss.ps);
00272     ExecAssignScanProjectionInfo(&scanstate->ss);
00273 
00274     return scanstate;
00275 }
00276 
00277 /* ----------------------------------------------------------------
00278  *      ExecEndValuesScan
00279  *
00280  *      frees any storage allocated through C routines.
00281  * ----------------------------------------------------------------
00282  */
00283 void
00284 ExecEndValuesScan(ValuesScanState *node)
00285 {
00286     /*
00287      * Free both exprcontexts
00288      */
00289     ExecFreeExprContext(&node->ss.ps);
00290     node->ss.ps.ps_ExprContext = node->rowcontext;
00291     ExecFreeExprContext(&node->ss.ps);
00292 
00293     /*
00294      * clean out the tuple table
00295      */
00296     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00297     ExecClearTuple(node->ss.ss_ScanTupleSlot);
00298 }
00299 
00300 /* ----------------------------------------------------------------
00301  *      ExecValuesMarkPos
00302  *
00303  *      Marks scan position.
00304  * ----------------------------------------------------------------
00305  */
00306 void
00307 ExecValuesMarkPos(ValuesScanState *node)
00308 {
00309     node->marked_idx = node->curr_idx;
00310 }
00311 
00312 /* ----------------------------------------------------------------
00313  *      ExecValuesRestrPos
00314  *
00315  *      Restores scan position.
00316  * ----------------------------------------------------------------
00317  */
00318 void
00319 ExecValuesRestrPos(ValuesScanState *node)
00320 {
00321     node->curr_idx = node->marked_idx;
00322 }
00323 
00324 /* ----------------------------------------------------------------
00325  *      ExecReScanValuesScan
00326  *
00327  *      Rescans the relation.
00328  * ----------------------------------------------------------------
00329  */
00330 void
00331 ExecReScanValuesScan(ValuesScanState *node)
00332 {
00333     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00334 
00335     ExecScanReScan(&node->ss);
00336 
00337     node->curr_idx = -1;
00338 }