LCOV - code coverage report
Current view: top level - src/backend/executor - nodeValuesscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 75 81 92.6 %
Date: 2019-06-19 16:07:09 Functions: 6 6 100.0 %
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-2019, 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 "jit/jit.h"
      29             : #include "utils/expandeddatum.h"
      30             : 
      31             : 
      32             : static TupleTableSlot *ValuesNext(ValuesScanState *node);
      33             : 
      34             : 
      35             : /* ----------------------------------------------------------------
      36             :  *                      Scan Support
      37             :  * ----------------------------------------------------------------
      38             :  */
      39             : 
      40             : /* ----------------------------------------------------------------
      41             :  *      ValuesNext
      42             :  *
      43             :  *      This is a workhorse for ExecValuesScan
      44             :  * ----------------------------------------------------------------
      45             :  */
      46             : static TupleTableSlot *
      47      141238 : ValuesNext(ValuesScanState *node)
      48             : {
      49             :     TupleTableSlot *slot;
      50             :     EState     *estate;
      51             :     ExprContext *econtext;
      52             :     ScanDirection direction;
      53             :     List       *exprlist;
      54             : 
      55             :     /*
      56             :      * get information from the estate and scan state
      57             :      */
      58      141238 :     estate = node->ss.ps.state;
      59      141238 :     direction = estate->es_direction;
      60      141238 :     slot = node->ss.ss_ScanTupleSlot;
      61      141238 :     econtext = node->rowcontext;
      62             : 
      63             :     /*
      64             :      * Get the next tuple. Return NULL if no more tuples.
      65             :      */
      66      141238 :     if (ScanDirectionIsForward(direction))
      67             :     {
      68      141238 :         if (node->curr_idx < node->array_len)
      69      141238 :             node->curr_idx++;
      70      141238 :         if (node->curr_idx < node->array_len)
      71       97066 :             exprlist = node->exprlists[node->curr_idx];
      72             :         else
      73       44172 :             exprlist = NIL;
      74             :     }
      75             :     else
      76             :     {
      77           0 :         if (node->curr_idx >= 0)
      78           0 :             node->curr_idx--;
      79           0 :         if (node->curr_idx >= 0)
      80           0 :             exprlist = node->exprlists[node->curr_idx];
      81             :         else
      82           0 :             exprlist = NIL;
      83             :     }
      84             : 
      85             :     /*
      86             :      * Always clear the result slot; this is appropriate if we are at the end
      87             :      * of the data, and if we're not, we still need it as the first step of
      88             :      * the store-virtual-tuple protocol.  It seems wise to clear the slot
      89             :      * before we reset the context it might have pointers into.
      90             :      */
      91      141238 :     ExecClearTuple(slot);
      92             : 
      93      141238 :     if (exprlist)
      94             :     {
      95             :         MemoryContext oldContext;
      96             :         List       *oldsubplans;
      97             :         List       *exprstatelist;
      98             :         Datum      *values;
      99             :         bool       *isnull;
     100             :         ListCell   *lc;
     101             :         int         resind;
     102             :         int         saved_jit_flags;
     103             : 
     104             :         /*
     105             :          * Get rid of any prior cycle's leftovers.  We use ReScanExprContext
     106             :          * not just ResetExprContext because we want any registered shutdown
     107             :          * callbacks to be called.
     108             :          */
     109       97066 :         ReScanExprContext(econtext);
     110             : 
     111             :         /*
     112             :          * Build the expression eval state in the econtext's per-tuple memory.
     113             :          * This is a tad unusual, but we want to delete the eval state again
     114             :          * when we move to the next row, to avoid growth of memory
     115             :          * requirements over a long values list.
     116             :          */
     117       97066 :         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
     118             : 
     119             :         /*
     120             :          * The expressions might contain SubPlans (this is currently only
     121             :          * possible if there's a sub-select containing a LATERAL reference,
     122             :          * otherwise sub-selects in a VALUES list should be InitPlans). Those
     123             :          * subplans will want to hook themselves into our subPlan list, which
     124             :          * would result in a corrupted list after we delete the eval state. We
     125             :          * can work around this by saving and restoring the subPlan list.
     126             :          * (There's no need for the functionality that would be enabled by
     127             :          * having the list entries, since the SubPlans aren't going to be
     128             :          * re-executed anyway.)
     129             :          */
     130       97066 :         oldsubplans = node->ss.ps.subPlan;
     131       97066 :         node->ss.ps.subPlan = NIL;
     132             : 
     133             :         /*
     134             :          * As the expressions are only ever used once, disable JIT for them.
     135             :          * This is worthwhile because it's common to insert significant
     136             :          * amounts of data via VALUES().
     137             :          */
     138       97066 :         saved_jit_flags = econtext->ecxt_estate->es_jit_flags;
     139       97066 :         econtext->ecxt_estate->es_jit_flags = PGJIT_NONE;
     140       97066 :         exprstatelist = ExecInitExprList(exprlist, &node->ss.ps);
     141       97066 :         econtext->ecxt_estate->es_jit_flags = saved_jit_flags;
     142             : 
     143       97066 :         node->ss.ps.subPlan = oldsubplans;
     144             : 
     145             :         /* parser should have checked all sublists are the same length */
     146             :         Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
     147             : 
     148             :         /*
     149             :          * Compute the expressions and build a virtual result tuple. We
     150             :          * already did ExecClearTuple(slot).
     151             :          */
     152       97066 :         values = slot->tts_values;
     153       97066 :         isnull = slot->tts_isnull;
     154             : 
     155       97066 :         resind = 0;
     156      204842 :         foreach(lc, exprstatelist)
     157             :         {
     158      107776 :             ExprState  *estate = (ExprState *) lfirst(lc);
     159      107776 :             Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor,
     160             :                                                    resind);
     161             : 
     162      107776 :             values[resind] = ExecEvalExpr(estate,
     163             :                                           econtext,
     164             :                                           &isnull[resind]);
     165             : 
     166             :             /*
     167             :              * We must force any R/W expanded datums to read-only state, in
     168             :              * case they are multiply referenced in the plan node's output
     169             :              * expressions, or in case we skip the output projection and the
     170             :              * output column is multiply referenced in higher plan nodes.
     171             :              */
     172      107776 :             values[resind] = MakeExpandedObjectReadOnly(values[resind],
     173             :                                                         isnull[resind],
     174             :                                                         attr->attlen);
     175             : 
     176      107776 :             resind++;
     177             :         }
     178             : 
     179       97066 :         MemoryContextSwitchTo(oldContext);
     180             : 
     181             :         /*
     182             :          * And return the virtual tuple.
     183             :          */
     184       97066 :         ExecStoreVirtualTuple(slot);
     185             :     }
     186             : 
     187      141238 :     return slot;
     188             : }
     189             : 
     190             : /*
     191             :  * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
     192             :  */
     193             : static bool
     194           2 : ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
     195             : {
     196             :     /* nothing to check */
     197           2 :     return true;
     198             : }
     199             : 
     200             : /* ----------------------------------------------------------------
     201             :  *      ExecValuesScan(node)
     202             :  *
     203             :  *      Scans the values lists sequentially and returns the next qualifying
     204             :  *      tuple.
     205             :  *      We call the ExecScan() routine and pass it the appropriate
     206             :  *      access method functions.
     207             :  * ----------------------------------------------------------------
     208             :  */
     209             : static TupleTableSlot *
     210      140636 : ExecValuesScan(PlanState *pstate)
     211             : {
     212      140636 :     ValuesScanState *node = castNode(ValuesScanState, pstate);
     213             : 
     214      140636 :     return ExecScan(&node->ss,
     215             :                     (ExecScanAccessMtd) ValuesNext,
     216             :                     (ExecScanRecheckMtd) ValuesRecheck);
     217             : }
     218             : 
     219             : /* ----------------------------------------------------------------
     220             :  *      ExecInitValuesScan
     221             :  * ----------------------------------------------------------------
     222             :  */
     223             : ValuesScanState *
     224        4292 : ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
     225             : {
     226             :     ValuesScanState *scanstate;
     227             :     TupleDesc   tupdesc;
     228             :     ListCell   *vtl;
     229             :     int         i;
     230             :     PlanState  *planstate;
     231             : 
     232             :     /*
     233             :      * ValuesScan should not have any children.
     234             :      */
     235             :     Assert(outerPlan(node) == NULL);
     236             :     Assert(innerPlan(node) == NULL);
     237             : 
     238             :     /*
     239             :      * create new ScanState for node
     240             :      */
     241        4292 :     scanstate = makeNode(ValuesScanState);
     242        4292 :     scanstate->ss.ps.plan = (Plan *) node;
     243        4292 :     scanstate->ss.ps.state = estate;
     244        4292 :     scanstate->ss.ps.ExecProcNode = ExecValuesScan;
     245             : 
     246             :     /*
     247             :      * Miscellaneous initialization
     248             :      */
     249        4292 :     planstate = &scanstate->ss.ps;
     250             : 
     251             :     /*
     252             :      * Create expression contexts.  We need two, one for per-sublist
     253             :      * processing and one for execScan.c to use for quals and projections. We
     254             :      * cheat a little by using ExecAssignExprContext() to build both.
     255             :      */
     256        4292 :     ExecAssignExprContext(estate, planstate);
     257        4292 :     scanstate->rowcontext = planstate->ps_ExprContext;
     258        4292 :     ExecAssignExprContext(estate, planstate);
     259             : 
     260             :     /*
     261             :      * Get info about values list, initialize scan slot with it.
     262             :      */
     263        4292 :     tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
     264        4292 :     ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);
     265             : 
     266             :     /*
     267             :      * Initialize result type and projection.
     268             :      */
     269        4292 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     270        4292 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     271             : 
     272             :     /*
     273             :      * initialize child expressions
     274             :      */
     275        4292 :     scanstate->ss.ps.qual =
     276        4292 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     277             : 
     278             :     /*
     279             :      * Other node-specific setup
     280             :      */
     281        4292 :     scanstate->curr_idx = -1;
     282        4292 :     scanstate->array_len = list_length(node->values_lists);
     283             : 
     284             :     /* convert list of sublists into array of sublists for easy addressing */
     285        4292 :     scanstate->exprlists = (List **)
     286        4292 :         palloc(scanstate->array_len * sizeof(List *));
     287        4292 :     i = 0;
     288       21652 :     foreach(vtl, node->values_lists)
     289             :     {
     290       17360 :         scanstate->exprlists[i++] = (List *) lfirst(vtl);
     291             :     }
     292             : 
     293        4292 :     return scanstate;
     294             : }
     295             : 
     296             : /* ----------------------------------------------------------------
     297             :  *      ExecEndValuesScan
     298             :  *
     299             :  *      frees any storage allocated through C routines.
     300             :  * ----------------------------------------------------------------
     301             :  */
     302             : void
     303        4228 : ExecEndValuesScan(ValuesScanState *node)
     304             : {
     305             :     /*
     306             :      * Free both exprcontexts
     307             :      */
     308        4228 :     ExecFreeExprContext(&node->ss.ps);
     309        4228 :     node->ss.ps.ps_ExprContext = node->rowcontext;
     310        4228 :     ExecFreeExprContext(&node->ss.ps);
     311             : 
     312             :     /*
     313             :      * clean out the tuple table
     314             :      */
     315        4228 :     if (node->ss.ps.ps_ResultTupleSlot)
     316         804 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     317        4228 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
     318        4228 : }
     319             : 
     320             : /* ----------------------------------------------------------------
     321             :  *      ExecReScanValuesScan
     322             :  *
     323             :  *      Rescans the relation.
     324             :  * ----------------------------------------------------------------
     325             :  */
     326             : void
     327       40138 : ExecReScanValuesScan(ValuesScanState *node)
     328             : {
     329       40138 :     if (node->ss.ps.ps_ResultTupleSlot)
     330           0 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     331             : 
     332       40138 :     ExecScanReScan(&node->ss);
     333             : 
     334       40138 :     node->curr_idx = -1;
     335       40138 : }

Generated by: LCOV version 1.13