LCOV - code coverage report
Current view: top level - src/backend/executor - nodeResult.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 52 64 81.2 %
Date: 2017-09-29 15:12:54 Functions: 4 6 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nodeResult.c
       4             :  *    support for constant nodes needing special code.
       5             :  *
       6             :  * DESCRIPTION
       7             :  *
       8             :  *      Result nodes are used in queries where no relations are scanned.
       9             :  *      Examples of such queries are:
      10             :  *
      11             :  *              select 1 * 2
      12             :  *
      13             :  *              insert into emp values ('mike', 15000)
      14             :  *
      15             :  *      (Remember that in an INSERT or UPDATE, we need a plan tree that
      16             :  *      generates the new rows.)
      17             :  *
      18             :  *      Result nodes are also used to optimise queries with constant
      19             :  *      qualifications (ie, quals that do not depend on the scanned data),
      20             :  *      such as:
      21             :  *
      22             :  *              select * from emp where 2 > 1
      23             :  *
      24             :  *      In this case, the plan generated is
      25             :  *
      26             :  *                      Result  (with 2 > 1 qual)
      27             :  *                      /
      28             :  *                 SeqScan (emp.*)
      29             :  *
      30             :  *      At runtime, the Result node evaluates the constant qual once,
      31             :  *      which is shown by EXPLAIN as a One-Time Filter.  If it's
      32             :  *      false, we can return an empty result set without running the
      33             :  *      controlled plan at all.  If it's true, we run the controlled
      34             :  *      plan normally and pass back the results.
      35             :  *
      36             :  *
      37             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
      38             :  * Portions Copyright (c) 1994, Regents of the University of California
      39             :  *
      40             :  * IDENTIFICATION
      41             :  *    src/backend/executor/nodeResult.c
      42             :  *
      43             :  *-------------------------------------------------------------------------
      44             :  */
      45             : 
      46             : #include "postgres.h"
      47             : 
      48             : #include "executor/executor.h"
      49             : #include "executor/nodeResult.h"
      50             : #include "miscadmin.h"
      51             : #include "utils/memutils.h"
      52             : 
      53             : 
      54             : /* ----------------------------------------------------------------
      55             :  *      ExecResult(node)
      56             :  *
      57             :  *      returns the tuples from the outer plan which satisfy the
      58             :  *      qualification clause.  Since result nodes with right
      59             :  *      subtrees are never planned, we ignore the right subtree
      60             :  *      entirely (for now).. -cim 10/7/89
      61             :  *
      62             :  *      The qualification containing only constant clauses are
      63             :  *      checked first before any processing is done. It always returns
      64             :  *      'nil' if the constant qualification is not satisfied.
      65             :  * ----------------------------------------------------------------
      66             :  */
      67             : static TupleTableSlot *
      68       30969 : ExecResult(PlanState *pstate)
      69             : {
      70       30969 :     ResultState *node = castNode(ResultState, pstate);
      71             :     TupleTableSlot *outerTupleSlot;
      72             :     PlanState  *outerPlan;
      73             :     ExprContext *econtext;
      74             : 
      75       30969 :     CHECK_FOR_INTERRUPTS();
      76             : 
      77       30969 :     econtext = node->ps.ps_ExprContext;
      78             : 
      79             :     /*
      80             :      * check constant qualifications like (2 > 1), if not already done
      81             :      */
      82       30969 :     if (node->rs_checkqual)
      83             :     {
      84         969 :         bool        qualResult = ExecQual(node->resconstantqual, econtext);
      85             : 
      86         969 :         node->rs_checkqual = false;
      87         969 :         if (!qualResult)
      88             :         {
      89         772 :             node->rs_done = true;
      90         772 :             return NULL;
      91             :         }
      92             :     }
      93             : 
      94             :     /*
      95             :      * Reset per-tuple memory context to free any expression evaluation
      96             :      * storage allocated in the previous tuple cycle.
      97             :      */
      98       30197 :     ResetExprContext(econtext);
      99             : 
     100             :     /*
     101             :      * if rs_done is true then it means that we were asked to return a
     102             :      * constant tuple and we already did the last time ExecResult() was
     103             :      * called, OR that we failed the constant qual check. Either way, now we
     104             :      * are through.
     105             :      */
     106       30197 :     while (!node->rs_done)
     107             :     {
     108       22573 :         outerPlan = outerPlanState(node);
     109             : 
     110       22573 :         if (outerPlan != NULL)
     111             :         {
     112             :             /*
     113             :              * retrieve tuples from the outer plan until there are no more.
     114             :              */
     115       10994 :             outerTupleSlot = ExecProcNode(outerPlan);
     116             : 
     117       10994 :             if (TupIsNull(outerTupleSlot))
     118         256 :                 return NULL;
     119             : 
     120             :             /*
     121             :              * prepare to compute projection expressions, which will expect to
     122             :              * access the input tuples as varno OUTER.
     123             :              */
     124       10738 :             econtext->ecxt_outertuple = outerTupleSlot;
     125             :         }
     126             :         else
     127             :         {
     128             :             /*
     129             :              * if we don't have an outer plan, then we are just generating the
     130             :              * results from a constant target list.  Do it only once.
     131             :              */
     132       11579 :             node->rs_done = true;
     133             :         }
     134             : 
     135             :         /* form the result tuple using ExecProject(), and return it */
     136       22317 :         return ExecProject(node->ps.ps_ProjInfo);
     137             :     }
     138             : 
     139        7624 :     return NULL;
     140             : }
     141             : 
     142             : /* ----------------------------------------------------------------
     143             :  *      ExecResultMarkPos
     144             :  * ----------------------------------------------------------------
     145             :  */
     146             : void
     147           0 : ExecResultMarkPos(ResultState *node)
     148             : {
     149           0 :     PlanState  *outerPlan = outerPlanState(node);
     150             : 
     151           0 :     if (outerPlan != NULL)
     152           0 :         ExecMarkPos(outerPlan);
     153             :     else
     154           0 :         elog(DEBUG2, "Result nodes do not support mark/restore");
     155           0 : }
     156             : 
     157             : /* ----------------------------------------------------------------
     158             :  *      ExecResultRestrPos
     159             :  * ----------------------------------------------------------------
     160             :  */
     161             : void
     162           0 : ExecResultRestrPos(ResultState *node)
     163             : {
     164           0 :     PlanState  *outerPlan = outerPlanState(node);
     165             : 
     166           0 :     if (outerPlan != NULL)
     167           0 :         ExecRestrPos(outerPlan);
     168             :     else
     169           0 :         elog(ERROR, "Result nodes do not support mark/restore");
     170           0 : }
     171             : 
     172             : /* ----------------------------------------------------------------
     173             :  *      ExecInitResult
     174             :  *
     175             :  *      Creates the run-time state information for the result node
     176             :  *      produced by the planner and initializes outer relations
     177             :  *      (child nodes).
     178             :  * ----------------------------------------------------------------
     179             :  */
     180             : ResultState *
     181       11846 : ExecInitResult(Result *node, EState *estate, int eflags)
     182             : {
     183             :     ResultState *resstate;
     184             : 
     185             :     /* check for unsupported flags */
     186       11846 :     Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) ||
     187             :            outerPlan(node) != NULL);
     188             : 
     189             :     /*
     190             :      * create state structure
     191             :      */
     192       11846 :     resstate = makeNode(ResultState);
     193       11846 :     resstate->ps.plan = (Plan *) node;
     194       11846 :     resstate->ps.state = estate;
     195       11846 :     resstate->ps.ExecProcNode = ExecResult;
     196             : 
     197       11846 :     resstate->rs_done = false;
     198       11846 :     resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
     199             : 
     200             :     /*
     201             :      * Miscellaneous initialization
     202             :      *
     203             :      * create expression context for node
     204             :      */
     205       11846 :     ExecAssignExprContext(estate, &resstate->ps);
     206             : 
     207             :     /*
     208             :      * tuple table initialization
     209             :      */
     210       11846 :     ExecInitResultTupleSlot(estate, &resstate->ps);
     211             : 
     212             :     /*
     213             :      * initialize child expressions
     214             :      */
     215       11846 :     resstate->ps.qual =
     216       11846 :         ExecInitQual(node->plan.qual, (PlanState *) resstate);
     217       11846 :     resstate->resconstantqual =
     218       11846 :         ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
     219             : 
     220             :     /*
     221             :      * initialize child nodes
     222             :      */
     223       11846 :     outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
     224             : 
     225             :     /*
     226             :      * we don't use inner plan
     227             :      */
     228       11846 :     Assert(innerPlan(node) == NULL);
     229             : 
     230             :     /*
     231             :      * initialize tuple type and projection info
     232             :      */
     233       11846 :     ExecAssignResultTypeFromTL(&resstate->ps);
     234       11846 :     ExecAssignProjectionInfo(&resstate->ps, NULL);
     235             : 
     236       11844 :     return resstate;
     237             : }
     238             : 
     239             : /* ----------------------------------------------------------------
     240             :  *      ExecEndResult
     241             :  *
     242             :  *      frees up storage allocated through C routines
     243             :  * ----------------------------------------------------------------
     244             :  */
     245             : void
     246        8836 : ExecEndResult(ResultState *node)
     247             : {
     248             :     /*
     249             :      * Free the exprcontext
     250             :      */
     251        8836 :     ExecFreeExprContext(&node->ps);
     252             : 
     253             :     /*
     254             :      * clean out the tuple table
     255             :      */
     256        8836 :     ExecClearTuple(node->ps.ps_ResultTupleSlot);
     257             : 
     258             :     /*
     259             :      * shut down subplans
     260             :      */
     261        8836 :     ExecEndNode(outerPlanState(node));
     262        8836 : }
     263             : 
     264             : void
     265        1249 : ExecReScanResult(ResultState *node)
     266             : {
     267        1249 :     node->rs_done = false;
     268        1249 :     node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
     269             : 
     270             :     /*
     271             :      * If chgParam of subnode is not null then plan will be re-scanned by
     272             :      * first ExecProcNode.
     273             :      */
     274        1935 :     if (node->ps.lefttree &&
     275         686 :         node->ps.lefttree->chgParam == NULL)
     276          12 :         ExecReScan(node->ps.lefttree);
     277        1249 : }

Generated by: LCOV version 1.11