LCOV - code coverage report
Current view: top level - src/backend/executor - nodeValuesscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 71 78 91.0 %
Date: 2017-09-29 15:12:54 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nodeValuesscan.c
       4             :  *    Support routines for scanning Values lists
       5             :  *    ("VALUES (...), (...), ..." in rangetable).
       6             :  *
       7             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *    src/backend/executor/nodeValuesscan.c
      13             :  *
      14             :  *-------------------------------------------------------------------------
      15             :  */
      16             : /*
      17             :  * INTERFACE ROUTINES
      18             :  *      ExecValuesScan          scans a values list.
      19             :  *      ExecValuesNext          retrieve next tuple in sequential order.
      20             :  *      ExecInitValuesScan      creates and initializes a valuesscan node.
      21             :  *      ExecEndValuesScan       releases any storage allocated.
      22             :  *      ExecReScanValuesScan    rescans the values list
      23             :  */
      24             : #include "postgres.h"
      25             : 
      26             : #include "executor/executor.h"
      27             : #include "executor/nodeValuesscan.h"
      28             : #include "utils/expandeddatum.h"
      29             : 
      30             : 
      31             : static TupleTableSlot *ValuesNext(ValuesScanState *node);
      32             : 
      33             : 
      34             : /* ----------------------------------------------------------------
      35             :  *                      Scan Support
      36             :  * ----------------------------------------------------------------
      37             :  */
      38             : 
      39             : /* ----------------------------------------------------------------
      40             :  *      ValuesNext
      41             :  *
      42             :  *      This is a workhorse for ExecValuesScan
      43             :  * ----------------------------------------------------------------
      44             :  */
      45             : static TupleTableSlot *
      46       32786 : ValuesNext(ValuesScanState *node)
      47             : {
      48             :     TupleTableSlot *slot;
      49             :     EState     *estate;
      50             :     ExprContext *econtext;
      51             :     ScanDirection direction;
      52             :     List       *exprlist;
      53             : 
      54             :     /*
      55             :      * get information from the estate and scan state
      56             :      */
      57       32786 :     estate = node->ss.ps.state;
      58       32786 :     direction = estate->es_direction;
      59       32786 :     slot = node->ss.ss_ScanTupleSlot;
      60       32786 :     econtext = node->rowcontext;
      61             : 
      62             :     /*
      63             :      * Get the next tuple. Return NULL if no more tuples.
      64             :      */
      65       32786 :     if (ScanDirectionIsForward(direction))
      66             :     {
      67       32786 :         if (node->curr_idx < node->array_len)
      68       32786 :             node->curr_idx++;
      69       32786 :         if (node->curr_idx < node->array_len)
      70       22217 :             exprlist = node->exprlists[node->curr_idx];
      71             :         else
      72       10569 :             exprlist = NIL;
      73             :     }
      74             :     else
      75             :     {
      76           0 :         if (node->curr_idx >= 0)
      77           0 :             node->curr_idx--;
      78           0 :         if (node->curr_idx >= 0)
      79           0 :             exprlist = node->exprlists[node->curr_idx];
      80             :         else
      81           0 :             exprlist = NIL;
      82             :     }
      83             : 
      84             :     /*
      85             :      * Always clear the result slot; this is appropriate if we are at the end
      86             :      * of the data, and if we're not, we still need it as the first step of
      87             :      * the store-virtual-tuple protocol.  It seems wise to clear the slot
      88             :      * before we reset the context it might have pointers into.
      89             :      */
      90       32786 :     ExecClearTuple(slot);
      91             : 
      92       32786 :     if (exprlist)
      93             :     {
      94             :         MemoryContext oldContext;
      95             :         List       *exprstatelist;
      96             :         Datum      *values;
      97             :         bool       *isnull;
      98             :         ListCell   *lc;
      99             :         int         resind;
     100             : 
     101             :         /*
     102             :          * Get rid of any prior cycle's leftovers.  We use ReScanExprContext
     103             :          * not just ResetExprContext because we want any registered shutdown
     104             :          * callbacks to be called.
     105             :          */
     106       22217 :         ReScanExprContext(econtext);
     107             : 
     108             :         /*
     109             :          * Build the expression eval state in the econtext's per-tuple memory.
     110             :          * This is a tad unusual, but we want to delete the eval state again
     111             :          * when we move to the next row, to avoid growth of memory
     112             :          * requirements over a long values list.
     113             :          */
     114       22217 :         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
     115             : 
     116             :         /*
     117             :          * Pass NULL, not my plan node, because we don't want anything in this
     118             :          * transient state linking into permanent state.  The only possibility
     119             :          * is a SubPlan, and there shouldn't be any (any subselects in the
     120             :          * VALUES list should be InitPlans).
     121             :          */
     122       22217 :         exprstatelist = ExecInitExprList(exprlist, NULL);
     123             : 
     124             :         /* parser should have checked all sublists are the same length */
     125       22217 :         Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
     126             : 
     127             :         /*
     128             :          * Compute the expressions and build a virtual result tuple. We
     129             :          * already did ExecClearTuple(slot).
     130             :          */
     131       22217 :         values = slot->tts_values;
     132       22217 :         isnull = slot->tts_isnull;
     133             : 
     134       22217 :         resind = 0;
     135       46150 :         foreach(lc, exprstatelist)
     136             :         {
     137       23933 :             ExprState  *estate = (ExprState *) lfirst(lc);
     138       23933 :             Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor,
     139             :                                                    resind);
     140             : 
     141       23933 :             values[resind] = ExecEvalExpr(estate,
     142             :                                           econtext,
     143             :                                           &isnull[resind]);
     144             : 
     145             :             /*
     146             :              * We must force any R/W expanded datums to read-only state, in
     147             :              * case they are multiply referenced in the plan node's output
     148             :              * expressions, or in case we skip the output projection and the
     149             :              * output column is multiply referenced in higher plan nodes.
     150             :              */
     151       23933 :             values[resind] = MakeExpandedObjectReadOnly(values[resind],
     152             :                                                         isnull[resind],
     153             :                                                         attr->attlen);
     154             : 
     155       23933 :             resind++;
     156             :         }
     157             : 
     158       22217 :         MemoryContextSwitchTo(oldContext);
     159             : 
     160             :         /*
     161             :          * And return the virtual tuple.
     162             :          */
     163       22217 :         ExecStoreVirtualTuple(slot);
     164             :     }
     165             : 
     166       32786 :     return slot;
     167             : }
     168             : 
     169             : /*
     170             :  * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
     171             :  */
     172             : static bool
     173           0 : ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
     174             : {
     175             :     /* nothing to check */
     176           0 :     return true;
     177             : }
     178             : 
     179             : /* ----------------------------------------------------------------
     180             :  *      ExecValuesScan(node)
     181             :  *
     182             :  *      Scans the values lists sequentially and returns the next qualifying
     183             :  *      tuple.
     184             :  *      We call the ExecScan() routine and pass it the appropriate
     185             :  *      access method functions.
     186             :  * ----------------------------------------------------------------
     187             :  */
     188             : static TupleTableSlot *
     189       32642 : ExecValuesScan(PlanState *pstate)
     190             : {
     191       32642 :     ValuesScanState *node = castNode(ValuesScanState, pstate);
     192             : 
     193       32642 :     return ExecScan(&node->ss,
     194             :                     (ExecScanAccessMtd) ValuesNext,
     195             :                     (ExecScanRecheckMtd) ValuesRecheck);
     196             : }
     197             : 
     198             : /* ----------------------------------------------------------------
     199             :  *      ExecInitValuesScan
     200             :  * ----------------------------------------------------------------
     201             :  */
     202             : ValuesScanState *
     203         587 : ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
     204             : {
     205             :     ValuesScanState *scanstate;
     206             :     TupleDesc   tupdesc;
     207             :     ListCell   *vtl;
     208             :     int         i;
     209             :     PlanState  *planstate;
     210             : 
     211             :     /*
     212             :      * ValuesScan should not have any children.
     213             :      */
     214         587 :     Assert(outerPlan(node) == NULL);
     215         587 :     Assert(innerPlan(node) == NULL);
     216             : 
     217             :     /*
     218             :      * create new ScanState for node
     219             :      */
     220         587 :     scanstate = makeNode(ValuesScanState);
     221         587 :     scanstate->ss.ps.plan = (Plan *) node;
     222         587 :     scanstate->ss.ps.state = estate;
     223         587 :     scanstate->ss.ps.ExecProcNode = ExecValuesScan;
     224             : 
     225             :     /*
     226             :      * Miscellaneous initialization
     227             :      */
     228         587 :     planstate = &scanstate->ss.ps;
     229             : 
     230             :     /*
     231             :      * Create expression contexts.  We need two, one for per-sublist
     232             :      * processing and one for execScan.c to use for quals and projections. We
     233             :      * cheat a little by using ExecAssignExprContext() to build both.
     234             :      */
     235         587 :     ExecAssignExprContext(estate, planstate);
     236         587 :     scanstate->rowcontext = planstate->ps_ExprContext;
     237         587 :     ExecAssignExprContext(estate, planstate);
     238             : 
     239             :     /*
     240             :      * tuple table initialization
     241             :      */
     242         587 :     ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
     243         587 :     ExecInitScanTupleSlot(estate, &scanstate->ss);
     244             : 
     245             :     /*
     246             :      * initialize child expressions
     247             :      */
     248         587 :     scanstate->ss.ps.qual =
     249         587 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     250             : 
     251             :     /*
     252             :      * get info about values list
     253             :      */
     254         587 :     tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
     255             : 
     256         587 :     ExecAssignScanType(&scanstate->ss, tupdesc);
     257             : 
     258             :     /*
     259             :      * Other node-specific setup
     260             :      */
     261         587 :     scanstate->curr_idx = -1;
     262         587 :     scanstate->array_len = list_length(node->values_lists);
     263             : 
     264             :     /* convert list of sublists into array of sublists for easy addressing */
     265         587 :     scanstate->exprlists = (List **)
     266         587 :         palloc(scanstate->array_len * sizeof(List *));
     267         587 :     i = 0;
     268        2867 :     foreach(vtl, node->values_lists)
     269             :     {
     270        2280 :         scanstate->exprlists[i++] = (List *) lfirst(vtl);
     271             :     }
     272             : 
     273             :     /*
     274             :      * Initialize result tuple type and projection info.
     275             :      */
     276         587 :     ExecAssignResultTypeFromTL(&scanstate->ss.ps);
     277         587 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     278             : 
     279         587 :     return scanstate;
     280             : }
     281             : 
     282             : /* ----------------------------------------------------------------
     283             :  *      ExecEndValuesScan
     284             :  *
     285             :  *      frees any storage allocated through C routines.
     286             :  * ----------------------------------------------------------------
     287             :  */
     288             : void
     289         581 : ExecEndValuesScan(ValuesScanState *node)
     290             : {
     291             :     /*
     292             :      * Free both exprcontexts
     293             :      */
     294         581 :     ExecFreeExprContext(&node->ss.ps);
     295         581 :     node->ss.ps.ps_ExprContext = node->rowcontext;
     296         581 :     ExecFreeExprContext(&node->ss.ps);
     297             : 
     298             :     /*
     299             :      * clean out the tuple table
     300             :      */
     301         581 :     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     302         581 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
     303         581 : }
     304             : 
     305             : /* ----------------------------------------------------------------
     306             :  *      ExecReScanValuesScan
     307             :  *
     308             :  *      Rescans the relation.
     309             :  * ----------------------------------------------------------------
     310             :  */
     311             : void
     312       10025 : ExecReScanValuesScan(ValuesScanState *node)
     313             : {
     314       10025 :     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     315             : 
     316       10025 :     ExecScanReScan(&node->ss);
     317             : 
     318       10025 :     node->curr_idx = -1;
     319       10025 : }

Generated by: LCOV version 1.11