LCOV - code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 233 270 86.3 %
Date: 2017-09-29 15:12:54 Functions: 26 28 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * execUtils.c
       4             :  *    miscellaneous executor utility routines
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/executor/execUtils.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : /*
      16             :  * INTERFACE ROUTINES
      17             :  *      CreateExecutorState     Create/delete executor working state
      18             :  *      FreeExecutorState
      19             :  *      CreateExprContext
      20             :  *      CreateStandaloneExprContext
      21             :  *      FreeExprContext
      22             :  *      ReScanExprContext
      23             :  *
      24             :  *      ExecAssignExprContext   Common code for plan node init routines.
      25             :  *      ExecAssignResultType
      26             :  *      etc
      27             :  *
      28             :  *      ExecOpenScanRelation    Common code for scan node init routines.
      29             :  *      ExecCloseScanRelation
      30             :  *
      31             :  *      executor_errposition    Report syntactic position of an error.
      32             :  *
      33             :  *      RegisterExprContextCallback    Register function shutdown callback
      34             :  *      UnregisterExprContextCallback  Deregister function shutdown callback
      35             :  *
      36             :  *      GetAttributeByName      Runtime extraction of columns from tuples.
      37             :  *      GetAttributeByNum
      38             :  *
      39             :  *   NOTES
      40             :  *      This file has traditionally been the place to stick misc.
      41             :  *      executor support stuff that doesn't really go anyplace else.
      42             :  */
      43             : 
      44             : #include "postgres.h"
      45             : 
      46             : #include "access/relscan.h"
      47             : #include "access/transam.h"
      48             : #include "executor/executor.h"
      49             : #include "mb/pg_wchar.h"
      50             : #include "nodes/nodeFuncs.h"
      51             : #include "parser/parsetree.h"
      52             : #include "storage/lmgr.h"
      53             : #include "utils/builtins.h"
      54             : #include "utils/memutils.h"
      55             : #include "utils/rel.h"
      56             : #include "utils/typcache.h"
      57             : 
      58             : 
      59             : static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
      60             : 
      61             : 
      62             : /* ----------------------------------------------------------------
      63             :  *               Executor state and memory management functions
      64             :  * ----------------------------------------------------------------
      65             :  */
      66             : 
      67             : /* ----------------
      68             :  *      CreateExecutorState
      69             :  *
      70             :  *      Create and initialize an EState node, which is the root of
      71             :  *      working storage for an entire Executor invocation.
      72             :  *
      73             :  * Principally, this creates the per-query memory context that will be
      74             :  * used to hold all working data that lives till the end of the query.
      75             :  * Note that the per-query context will become a child of the caller's
      76             :  * CurrentMemoryContext.
      77             :  * ----------------
      78             :  */
      79             : EState *
      80       36146 : CreateExecutorState(void)
      81             : {
      82             :     EState     *estate;
      83             :     MemoryContext qcontext;
      84             :     MemoryContext oldcontext;
      85             : 
      86             :     /*
      87             :      * Create the per-query context for this Executor run.
      88             :      */
      89       36146 :     qcontext = AllocSetContextCreate(CurrentMemoryContext,
      90             :                                      "ExecutorState",
      91             :                                      ALLOCSET_DEFAULT_SIZES);
      92             : 
      93             :     /*
      94             :      * Make the EState node within the per-query context.  This way, we don't
      95             :      * need a separate pfree() operation for it at shutdown.
      96             :      */
      97       36146 :     oldcontext = MemoryContextSwitchTo(qcontext);
      98             : 
      99       36146 :     estate = makeNode(EState);
     100             : 
     101             :     /*
     102             :      * Initialize all fields of the Executor State structure
     103             :      */
     104       36146 :     estate->es_direction = ForwardScanDirection;
     105       36146 :     estate->es_snapshot = InvalidSnapshot;   /* caller must initialize this */
     106       36146 :     estate->es_crosscheck_snapshot = InvalidSnapshot;    /* no crosscheck */
     107       36146 :     estate->es_range_table = NIL;
     108       36146 :     estate->es_plannedstmt = NULL;
     109             : 
     110       36146 :     estate->es_junkFilter = NULL;
     111             : 
     112       36146 :     estate->es_output_cid = (CommandId) 0;
     113             : 
     114       36146 :     estate->es_result_relations = NULL;
     115       36146 :     estate->es_num_result_relations = 0;
     116       36146 :     estate->es_result_relation_info = NULL;
     117             : 
     118       36146 :     estate->es_root_result_relations = NULL;
     119       36146 :     estate->es_num_root_result_relations = 0;
     120             : 
     121       36146 :     estate->es_leaf_result_relations = NIL;
     122             : 
     123       36146 :     estate->es_trig_target_relations = NIL;
     124       36146 :     estate->es_trig_tuple_slot = NULL;
     125       36146 :     estate->es_trig_oldtup_slot = NULL;
     126       36146 :     estate->es_trig_newtup_slot = NULL;
     127             : 
     128       36146 :     estate->es_param_list_info = NULL;
     129       36146 :     estate->es_param_exec_vals = NULL;
     130             : 
     131       36146 :     estate->es_queryEnv = NULL;
     132             : 
     133       36146 :     estate->es_query_cxt = qcontext;
     134             : 
     135       36146 :     estate->es_tupleTable = NIL;
     136             : 
     137       36146 :     estate->es_rowMarks = NIL;
     138             : 
     139       36146 :     estate->es_processed = 0;
     140       36146 :     estate->es_lastoid = InvalidOid;
     141             : 
     142       36146 :     estate->es_top_eflags = 0;
     143       36146 :     estate->es_instrument = 0;
     144       36146 :     estate->es_finished = false;
     145             : 
     146       36146 :     estate->es_exprcontexts = NIL;
     147             : 
     148       36146 :     estate->es_subplanstates = NIL;
     149             : 
     150       36146 :     estate->es_auxmodifytables = NIL;
     151             : 
     152       36146 :     estate->es_per_tuple_exprcontext = NULL;
     153             : 
     154       36146 :     estate->es_epqTuple = NULL;
     155       36146 :     estate->es_epqTupleSet = NULL;
     156       36146 :     estate->es_epqScanDone = NULL;
     157       36146 :     estate->es_sourceText = NULL;
     158             : 
     159             :     /*
     160             :      * Return the executor state structure
     161             :      */
     162       36146 :     MemoryContextSwitchTo(oldcontext);
     163             : 
     164       36146 :     return estate;
     165             : }
     166             : 
     167             : /* ----------------
     168             :  *      FreeExecutorState
     169             :  *
     170             :  *      Release an EState along with all remaining working storage.
     171             :  *
     172             :  * Note: this is not responsible for releasing non-memory resources,
     173             :  * such as open relations or buffer pins.  But it will shut down any
     174             :  * still-active ExprContexts within the EState.  That is sufficient
     175             :  * cleanup for situations where the EState has only been used for expression
     176             :  * evaluation, and not to run a complete Plan.
     177             :  *
     178             :  * This can be called in any memory context ... so long as it's not one
     179             :  * of the ones to be freed.
     180             :  * ----------------
     181             :  */
     182             : void
     183       32367 : FreeExecutorState(EState *estate)
     184             : {
     185             :     /*
     186             :      * Shut down and free any remaining ExprContexts.  We do this explicitly
     187             :      * to ensure that any remaining shutdown callbacks get called (since they
     188             :      * might need to release resources that aren't simply memory within the
     189             :      * per-query memory context).
     190             :      */
     191      126350 :     while (estate->es_exprcontexts)
     192             :     {
     193             :         /*
     194             :          * XXX: seems there ought to be a faster way to implement this than
     195             :          * repeated list_delete(), no?
     196             :          */
     197       61616 :         FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
     198             :                         true);
     199             :         /* FreeExprContext removed the list link for us */
     200             :     }
     201             : 
     202             :     /*
     203             :      * Free the per-query memory context, thereby releasing all working
     204             :      * memory, including the EState node itself.
     205             :      */
     206       32367 :     MemoryContextDelete(estate->es_query_cxt);
     207       32367 : }
     208             : 
     209             : /* ----------------
     210             :  *      CreateExprContext
     211             :  *
     212             :  *      Create a context for expression evaluation within an EState.
     213             :  *
     214             :  * An executor run may require multiple ExprContexts (we usually make one
     215             :  * for each Plan node, and a separate one for per-output-tuple processing
     216             :  * such as constraint checking).  Each ExprContext has its own "per-tuple"
     217             :  * memory context.
     218             :  *
     219             :  * Note we make no assumption about the caller's memory context.
     220             :  * ----------------
     221             :  */
     222             : ExprContext *
     223       78189 : CreateExprContext(EState *estate)
     224             : {
     225             :     ExprContext *econtext;
     226             :     MemoryContext oldcontext;
     227             : 
     228             :     /* Create the ExprContext node within the per-query memory context */
     229       78189 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     230             : 
     231       78189 :     econtext = makeNode(ExprContext);
     232             : 
     233             :     /* Initialize fields of ExprContext */
     234       78189 :     econtext->ecxt_scantuple = NULL;
     235       78189 :     econtext->ecxt_innertuple = NULL;
     236       78189 :     econtext->ecxt_outertuple = NULL;
     237             : 
     238       78189 :     econtext->ecxt_per_query_memory = estate->es_query_cxt;
     239             : 
     240             :     /*
     241             :      * Create working memory for expression evaluation in this context.
     242             :      */
     243       78189 :     econtext->ecxt_per_tuple_memory =
     244       78189 :         AllocSetContextCreate(estate->es_query_cxt,
     245             :                               "ExprContext",
     246             :                               ALLOCSET_DEFAULT_SIZES);
     247             : 
     248       78189 :     econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
     249       78189 :     econtext->ecxt_param_list_info = estate->es_param_list_info;
     250             : 
     251       78189 :     econtext->ecxt_aggvalues = NULL;
     252       78189 :     econtext->ecxt_aggnulls = NULL;
     253             : 
     254       78189 :     econtext->caseValue_datum = (Datum) 0;
     255       78189 :     econtext->caseValue_isNull = true;
     256             : 
     257       78189 :     econtext->domainValue_datum = (Datum) 0;
     258       78189 :     econtext->domainValue_isNull = true;
     259             : 
     260       78189 :     econtext->ecxt_estate = estate;
     261             : 
     262       78189 :     econtext->ecxt_callbacks = NULL;
     263             : 
     264             :     /*
     265             :      * Link the ExprContext into the EState to ensure it is shut down when the
     266             :      * EState is freed.  Because we use lcons(), shutdowns will occur in
     267             :      * reverse order of creation, which may not be essential but can't hurt.
     268             :      */
     269       78189 :     estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
     270             : 
     271       78189 :     MemoryContextSwitchTo(oldcontext);
     272             : 
     273       78189 :     return econtext;
     274             : }
     275             : 
     276             : /* ----------------
     277             :  *      CreateStandaloneExprContext
     278             :  *
     279             :  *      Create a context for standalone expression evaluation.
     280             :  *
     281             :  * An ExprContext made this way can be used for evaluation of expressions
     282             :  * that contain no Params, subplans, or Var references (it might work to
     283             :  * put tuple references into the scantuple field, but it seems unwise).
     284             :  *
     285             :  * The ExprContext struct is allocated in the caller's current memory
     286             :  * context, which also becomes its "per query" context.
     287             :  *
     288             :  * It is caller's responsibility to free the ExprContext when done,
     289             :  * or at least ensure that any shutdown callbacks have been called
     290             :  * (ReScanExprContext() is suitable).  Otherwise, non-memory resources
     291             :  * might be leaked.
     292             :  * ----------------
     293             :  */
     294             : ExprContext *
     295         318 : CreateStandaloneExprContext(void)
     296             : {
     297             :     ExprContext *econtext;
     298             : 
     299             :     /* Create the ExprContext node within the caller's memory context */
     300         318 :     econtext = makeNode(ExprContext);
     301             : 
     302             :     /* Initialize fields of ExprContext */
     303         318 :     econtext->ecxt_scantuple = NULL;
     304         318 :     econtext->ecxt_innertuple = NULL;
     305         318 :     econtext->ecxt_outertuple = NULL;
     306             : 
     307         318 :     econtext->ecxt_per_query_memory = CurrentMemoryContext;
     308             : 
     309             :     /*
     310             :      * Create working memory for expression evaluation in this context.
     311             :      */
     312         318 :     econtext->ecxt_per_tuple_memory =
     313         318 :         AllocSetContextCreate(CurrentMemoryContext,
     314             :                               "ExprContext",
     315             :                               ALLOCSET_DEFAULT_SIZES);
     316             : 
     317         318 :     econtext->ecxt_param_exec_vals = NULL;
     318         318 :     econtext->ecxt_param_list_info = NULL;
     319             : 
     320         318 :     econtext->ecxt_aggvalues = NULL;
     321         318 :     econtext->ecxt_aggnulls = NULL;
     322             : 
     323         318 :     econtext->caseValue_datum = (Datum) 0;
     324         318 :     econtext->caseValue_isNull = true;
     325             : 
     326         318 :     econtext->domainValue_datum = (Datum) 0;
     327         318 :     econtext->domainValue_isNull = true;
     328             : 
     329         318 :     econtext->ecxt_estate = NULL;
     330             : 
     331         318 :     econtext->ecxt_callbacks = NULL;
     332             : 
     333         318 :     return econtext;
     334             : }
     335             : 
     336             : /* ----------------
     337             :  *      FreeExprContext
     338             :  *
     339             :  *      Free an expression context, including calling any remaining
     340             :  *      shutdown callbacks.
     341             :  *
     342             :  * Since we free the temporary context used for expression evaluation,
     343             :  * any previously computed pass-by-reference expression result will go away!
     344             :  *
     345             :  * If isCommit is false, we are being called in error cleanup, and should
     346             :  * not call callbacks but only release memory.  (It might be better to call
     347             :  * the callbacks and pass the isCommit flag to them, but that would require
     348             :  * more invasive code changes than currently seems justified.)
     349             :  *
     350             :  * Note we make no assumption about the caller's memory context.
     351             :  * ----------------
     352             :  */
     353             : void
     354       74106 : FreeExprContext(ExprContext *econtext, bool isCommit)
     355             : {
     356             :     EState     *estate;
     357             : 
     358             :     /* Call any registered callbacks */
     359       74106 :     ShutdownExprContext(econtext, isCommit);
     360             :     /* And clean up the memory used */
     361       74106 :     MemoryContextDelete(econtext->ecxt_per_tuple_memory);
     362             :     /* Unlink self from owning EState, if any */
     363       74106 :     estate = econtext->ecxt_estate;
     364       74106 :     if (estate)
     365       74106 :         estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
     366             :                                                   econtext);
     367             :     /* And delete the ExprContext node */
     368       74106 :     pfree(econtext);
     369       74106 : }
     370             : 
     371             : /*
     372             :  * ReScanExprContext
     373             :  *
     374             :  *      Reset an expression context in preparation for a rescan of its
     375             :  *      plan node.  This requires calling any registered shutdown callbacks,
     376             :  *      since any partially complete set-returning-functions must be canceled.
     377             :  *
     378             :  * Note we make no assumption about the caller's memory context.
     379             :  */
     380             : void
     381       91563 : ReScanExprContext(ExprContext *econtext)
     382             : {
     383             :     /* Call any registered callbacks */
     384       91563 :     ShutdownExprContext(econtext, true);
     385             :     /* And clean up the memory used */
     386       91563 :     MemoryContextReset(econtext->ecxt_per_tuple_memory);
     387       91563 : }
     388             : 
     389             : /*
     390             :  * Build a per-output-tuple ExprContext for an EState.
     391             :  *
     392             :  * This is normally invoked via GetPerTupleExprContext() macro,
     393             :  * not directly.
     394             :  */
     395             : ExprContext *
     396       12033 : MakePerTupleExprContext(EState *estate)
     397             : {
     398       12033 :     if (estate->es_per_tuple_exprcontext == NULL)
     399       12033 :         estate->es_per_tuple_exprcontext = CreateExprContext(estate);
     400             : 
     401       12033 :     return estate->es_per_tuple_exprcontext;
     402             : }
     403             : 
     404             : 
     405             : /* ----------------------------------------------------------------
     406             :  *               miscellaneous node-init support functions
     407             :  *
     408             :  * Note: all of these are expected to be called with CurrentMemoryContext
     409             :  * equal to the per-query memory context.
     410             :  * ----------------------------------------------------------------
     411             :  */
     412             : 
     413             : /* ----------------
     414             :  *      ExecAssignExprContext
     415             :  *
     416             :  *      This initializes the ps_ExprContext field.  It is only necessary
     417             :  *      to do this for nodes which use ExecQual or ExecProject
     418             :  *      because those routines require an econtext. Other nodes that
     419             :  *      don't have to evaluate expressions don't need to do this.
     420             :  * ----------------
     421             :  */
     422             : void
     423       53096 : ExecAssignExprContext(EState *estate, PlanState *planstate)
     424             : {
     425       53096 :     planstate->ps_ExprContext = CreateExprContext(estate);
     426       53096 : }
     427             : 
     428             : /* ----------------
     429             :  *      ExecAssignResultType
     430             :  * ----------------
     431             :  */
     432             : void
     433       50676 : ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
     434             : {
     435       50676 :     TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
     436             : 
     437       50676 :     ExecSetSlotDescriptor(slot, tupDesc);
     438       50676 : }
     439             : 
     440             : /* ----------------
     441             :  *      ExecAssignResultTypeFromTL
     442             :  * ----------------
     443             :  */
     444             : void
     445       46192 : ExecAssignResultTypeFromTL(PlanState *planstate)
     446             : {
     447             :     bool        hasoid;
     448             :     TupleDesc   tupDesc;
     449             : 
     450       46192 :     if (ExecContextForcesOids(planstate, &hasoid))
     451             :     {
     452             :         /* context forces OID choice; hasoid is now set correctly */
     453             :     }
     454             :     else
     455             :     {
     456             :         /* given free choice, don't leave space for OIDs in result tuples */
     457       40599 :         hasoid = false;
     458             :     }
     459             : 
     460             :     /*
     461             :      * ExecTypeFromTL needs the parse-time representation of the tlist, not a
     462             :      * list of ExprStates.  This is good because some plan nodes don't bother
     463             :      * to set up planstate->targetlist ...
     464             :      */
     465       46192 :     tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
     466       46192 :     ExecAssignResultType(planstate, tupDesc);
     467       46192 : }
     468             : 
     469             : /* ----------------
     470             :  *      ExecGetResultType
     471             :  * ----------------
     472             :  */
     473             : TupleDesc
     474       36304 : ExecGetResultType(PlanState *planstate)
     475             : {
     476       36304 :     TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
     477             : 
     478       36304 :     return slot->tts_tupleDescriptor;
     479             : }
     480             : 
     481             : 
     482             : /* ----------------
     483             :  *      ExecAssignProjectionInfo
     484             :  *
     485             :  * forms the projection information from the node's targetlist
     486             :  *
     487             :  * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
     488             :  * for a relation-scan node, can pass NULL for upper-level nodes
     489             :  * ----------------
     490             :  */
     491             : void
     492       31718 : ExecAssignProjectionInfo(PlanState *planstate,
     493             :                          TupleDesc inputDesc)
     494             : {
     495       31716 :     planstate->ps_ProjInfo =
     496       31718 :         ExecBuildProjectionInfo(planstate->plan->targetlist,
     497             :                                 planstate->ps_ExprContext,
     498             :                                 planstate->ps_ResultTupleSlot,
     499             :                                 planstate,
     500             :                                 inputDesc);
     501       31716 : }
     502             : 
     503             : 
     504             : /* ----------------
     505             :  *      ExecFreeExprContext
     506             :  *
     507             :  * A plan node's ExprContext should be freed explicitly during executor
     508             :  * shutdown because there may be shutdown callbacks to call.  (Other resources
     509             :  * made by the above routines, such as projection info, don't need to be freed
     510             :  * explicitly because they're just memory in the per-query memory context.)
     511             :  *
     512             :  * However ... there is no particular need to do it during ExecEndNode,
     513             :  * because FreeExecutorState will free any remaining ExprContexts within
     514             :  * the EState.  Letting FreeExecutorState do it allows the ExprContexts to
     515             :  * be freed in reverse order of creation, rather than order of creation as
     516             :  * will happen if we delete them here, which saves O(N^2) work in the list
     517             :  * cleanup inside FreeExprContext.
     518             :  * ----------------
     519             :  */
     520             : void
     521       36341 : ExecFreeExprContext(PlanState *planstate)
     522             : {
     523             :     /*
     524             :      * Per above discussion, don't actually delete the ExprContext. We do
     525             :      * unlink it from the plan node, though.
     526             :      */
     527       36341 :     planstate->ps_ExprContext = NULL;
     528       36341 : }
     529             : 
     530             : /* ----------------------------------------------------------------
     531             :  *      the following scan type support functions are for
     532             :  *      those nodes which are stubborn and return tuples in
     533             :  *      their Scan tuple slot instead of their Result tuple
     534             :  *      slot..  luck fur us, these nodes do not do projections
     535             :  *      so we don't have to worry about getting the ProjectionInfo
     536             :  *      right for them...  -cim 6/3/91
     537             :  * ----------------------------------------------------------------
     538             :  */
     539             : 
     540             : /* ----------------
     541             :  *      ExecAssignScanType
     542             :  * ----------------
     543             :  */
     544             : void
     545       27581 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
     546             : {
     547       27581 :     TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
     548             : 
     549       27581 :     ExecSetSlotDescriptor(slot, tupDesc);
     550       27581 : }
     551             : 
     552             : /* ----------------
     553             :  *      ExecAssignScanTypeFromOuterPlan
     554             :  * ----------------
     555             :  */
     556             : void
     557        5900 : ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
     558             : {
     559             :     PlanState  *outerPlan;
     560             :     TupleDesc   tupDesc;
     561             : 
     562        5900 :     outerPlan = outerPlanState(scanstate);
     563        5900 :     tupDesc = ExecGetResultType(outerPlan);
     564             : 
     565        5900 :     ExecAssignScanType(scanstate, tupDesc);
     566        5900 : }
     567             : 
     568             : 
     569             : /* ----------------------------------------------------------------
     570             :  *                Scan node support
     571             :  * ----------------------------------------------------------------
     572             :  */
     573             : 
     574             : /* ----------------------------------------------------------------
     575             :  *      ExecRelationIsTargetRelation
     576             :  *
     577             :  *      Detect whether a relation (identified by rangetable index)
     578             :  *      is one of the target relations of the query.
     579             :  * ----------------------------------------------------------------
     580             :  */
     581             : bool
     582       27227 : ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
     583             : {
     584             :     ResultRelInfo *resultRelInfos;
     585             :     int         i;
     586             : 
     587       27227 :     resultRelInfos = estate->es_result_relations;
     588       28619 :     for (i = 0; i < estate->es_num_result_relations; i++)
     589             :     {
     590        2647 :         if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
     591        1255 :             return true;
     592             :     }
     593       25972 :     return false;
     594             : }
     595             : 
     596             : /* ----------------------------------------------------------------
     597             :  *      ExecOpenScanRelation
     598             :  *
     599             :  *      Open the heap relation to be scanned by a base-level scan plan node.
     600             :  *      This should be called during the node's ExecInit routine.
     601             :  *
     602             :  * By default, this acquires AccessShareLock on the relation.  However,
     603             :  * if the relation was already locked by InitPlan, we don't need to acquire
     604             :  * any additional lock.  This saves trips to the shared lock manager.
     605             :  * ----------------------------------------------------------------
     606             :  */
     607             : Relation
     608       19058 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
     609             : {
     610             :     Relation    rel;
     611             :     Oid         reloid;
     612             :     LOCKMODE    lockmode;
     613             : 
     614             :     /*
     615             :      * Determine the lock type we need.  First, scan to see if target relation
     616             :      * is a result relation.  If not, check if it's a FOR UPDATE/FOR SHARE
     617             :      * relation.  In either of those cases, we got the lock already.
     618             :      */
     619       19058 :     lockmode = AccessShareLock;
     620       19058 :     if (ExecRelationIsTargetRelation(estate, scanrelid))
     621        1008 :         lockmode = NoLock;
     622             :     else
     623             :     {
     624             :         /* Keep this check in sync with InitPlan! */
     625       18050 :         ExecRowMark *erm = ExecFindRowMark(estate, scanrelid, true);
     626             : 
     627       18050 :         if (erm != NULL && erm->relation != NULL)
     628         548 :             lockmode = NoLock;
     629             :     }
     630             : 
     631             :     /* Open the relation and acquire lock as needed */
     632       19058 :     reloid = getrelid(scanrelid, estate->es_range_table);
     633       19058 :     rel = heap_open(reloid, lockmode);
     634             : 
     635             :     /*
     636             :      * Complain if we're attempting a scan of an unscannable relation, except
     637             :      * when the query won't actually be run.  This is a slightly klugy place
     638             :      * to do this, perhaps, but there is no better place.
     639             :      */
     640       36655 :     if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
     641       17597 :         !RelationIsScannable(rel))
     642           2 :         ereport(ERROR,
     643             :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
     644             :                  errmsg("materialized view \"%s\" has not been populated",
     645             :                         RelationGetRelationName(rel)),
     646             :                  errhint("Use the REFRESH MATERIALIZED VIEW command.")));
     647             : 
     648       19056 :     return rel;
     649             : }
     650             : 
     651             : /* ----------------------------------------------------------------
     652             :  *      ExecCloseScanRelation
     653             :  *
     654             :  *      Close the heap relation scanned by a base-level scan plan node.
     655             :  *      This should be called during the node's ExecEnd routine.
     656             :  *
     657             :  * Currently, we do not release the lock acquired by ExecOpenScanRelation.
     658             :  * This lock should be held till end of transaction.  (There is a faction
     659             :  * that considers this too much locking, however.)
     660             :  *
     661             :  * If we did want to release the lock, we'd have to repeat the logic in
     662             :  * ExecOpenScanRelation in order to figure out what to release.
     663             :  * ----------------------------------------------------------------
     664             :  */
     665             : void
     666       18802 : ExecCloseScanRelation(Relation scanrel)
     667             : {
     668       18802 :     heap_close(scanrel, NoLock);
     669       18802 : }
     670             : 
     671             : /*
     672             :  * UpdateChangedParamSet
     673             :  *      Add changed parameters to a plan node's chgParam set
     674             :  */
     675             : void
     676        5124 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
     677             : {
     678             :     Bitmapset  *parmset;
     679             : 
     680             :     /*
     681             :      * The plan node only depends on params listed in its allParam set. Don't
     682             :      * include anything else into its chgParam set.
     683             :      */
     684        5124 :     parmset = bms_intersect(node->plan->allParam, newchg);
     685             : 
     686             :     /*
     687             :      * Keep node->chgParam == NULL if there's not actually any members; this
     688             :      * allows the simplest possible tests in executor node files.
     689             :      */
     690        5124 :     if (!bms_is_empty(parmset))
     691        4216 :         node->chgParam = bms_join(node->chgParam, parmset);
     692             :     else
     693         908 :         bms_free(parmset);
     694        5124 : }
     695             : 
     696             : /*
     697             :  * executor_errposition
     698             :  *      Report an execution-time cursor position, if possible.
     699             :  *
     700             :  * This is expected to be used within an ereport() call.  The return value
     701             :  * is a dummy (always 0, in fact).
     702             :  *
     703             :  * The locations stored in parsetrees are byte offsets into the source string.
     704             :  * We have to convert them to 1-based character indexes for reporting to
     705             :  * clients.  (We do things this way to avoid unnecessary overhead in the
     706             :  * normal non-error case: computing character indexes would be much more
     707             :  * expensive than storing token offsets.)
     708             :  */
     709             : int
     710           0 : executor_errposition(EState *estate, int location)
     711             : {
     712             :     int         pos;
     713             : 
     714             :     /* No-op if location was not provided */
     715           0 :     if (location < 0)
     716           0 :         return 0;
     717             :     /* Can't do anything if source text is not available */
     718           0 :     if (estate == NULL || estate->es_sourceText == NULL)
     719           0 :         return 0;
     720             :     /* Convert offset to character number */
     721           0 :     pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
     722             :     /* And pass it to the ereport mechanism */
     723           0 :     return errposition(pos);
     724             : }
     725             : 
     726             : /*
     727             :  * Register a shutdown callback in an ExprContext.
     728             :  *
     729             :  * Shutdown callbacks will be called (in reverse order of registration)
     730             :  * when the ExprContext is deleted or rescanned.  This provides a hook
     731             :  * for functions called in the context to do any cleanup needed --- it's
     732             :  * particularly useful for functions returning sets.  Note that the
     733             :  * callback will *not* be called in the event that execution is aborted
     734             :  * by an error.
     735             :  */
     736             : void
     737       14172 : RegisterExprContextCallback(ExprContext *econtext,
     738             :                             ExprContextCallbackFunction function,
     739             :                             Datum arg)
     740             : {
     741             :     ExprContext_CB *ecxt_callback;
     742             : 
     743             :     /* Save the info in appropriate memory context */
     744       14172 :     ecxt_callback = (ExprContext_CB *)
     745       14172 :         MemoryContextAlloc(econtext->ecxt_per_query_memory,
     746             :                            sizeof(ExprContext_CB));
     747             : 
     748       14172 :     ecxt_callback->function = function;
     749       14172 :     ecxt_callback->arg = arg;
     750             : 
     751             :     /* link to front of list for appropriate execution order */
     752       14172 :     ecxt_callback->next = econtext->ecxt_callbacks;
     753       14172 :     econtext->ecxt_callbacks = ecxt_callback;
     754       14172 : }
     755             : 
     756             : /*
     757             :  * Deregister a shutdown callback in an ExprContext.
     758             :  *
     759             :  * Any list entries matching the function and arg will be removed.
     760             :  * This can be used if it's no longer necessary to call the callback.
     761             :  */
     762             : void
     763       12794 : UnregisterExprContextCallback(ExprContext *econtext,
     764             :                               ExprContextCallbackFunction function,
     765             :                               Datum arg)
     766             : {
     767             :     ExprContext_CB **prev_callback;
     768             :     ExprContext_CB *ecxt_callback;
     769             : 
     770       12794 :     prev_callback = &econtext->ecxt_callbacks;
     771             : 
     772       43431 :     while ((ecxt_callback = *prev_callback) != NULL)
     773             :     {
     774       17843 :         if (ecxt_callback->function == function && ecxt_callback->arg == arg)
     775             :         {
     776       12794 :             *prev_callback = ecxt_callback->next;
     777       12794 :             pfree(ecxt_callback);
     778             :         }
     779             :         else
     780        5049 :             prev_callback = &ecxt_callback->next;
     781             :     }
     782       12794 : }
     783             : 
     784             : /*
     785             :  * Call all the shutdown callbacks registered in an ExprContext.
     786             :  *
     787             :  * The callback list is emptied (important in case this is only a rescan
     788             :  * reset, and not deletion of the ExprContext).
     789             :  *
     790             :  * If isCommit is false, just clean the callback list but don't call 'em.
     791             :  * (See comment for FreeExprContext.)
     792             :  */
     793             : static void
     794      165669 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
     795             : {
     796             :     ExprContext_CB *ecxt_callback;
     797             :     MemoryContext oldcontext;
     798             : 
     799             :     /* Fast path in normal case where there's nothing to do. */
     800      165669 :     if (econtext->ecxt_callbacks == NULL)
     801      330244 :         return;
     802             : 
     803             :     /*
     804             :      * Call the callbacks in econtext's per-tuple context.  This ensures that
     805             :      * any memory they might leak will get cleaned up.
     806             :      */
     807        1094 :     oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
     808             : 
     809             :     /*
     810             :      * Call each callback function in reverse registration order.
     811             :      */
     812        3539 :     while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
     813             :     {
     814        1351 :         econtext->ecxt_callbacks = ecxt_callback->next;
     815        1351 :         if (isCommit)
     816        1351 :             (*ecxt_callback->function) (ecxt_callback->arg);
     817        1351 :         pfree(ecxt_callback);
     818             :     }
     819             : 
     820        1094 :     MemoryContextSwitchTo(oldcontext);
     821             : }
     822             : 
     823             : /*
     824             :  * ExecLockNonLeafAppendTables
     825             :  *
     826             :  * Locks, if necessary, the tables indicated by the RT indexes contained in
     827             :  * the partitioned_rels list.  These are the non-leaf tables in the partition
     828             :  * tree controlled by a given Append or MergeAppend node.
     829             :  */
     830             : void
     831         636 : ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
     832             : {
     833         636 :     PlannedStmt *stmt = estate->es_plannedstmt;
     834             :     ListCell   *lc;
     835             : 
     836         725 :     foreach(lc, partitioned_rels)
     837             :     {
     838             :         ListCell   *l;
     839          89 :         Index       rti = lfirst_int(lc);
     840          89 :         bool        is_result_rel = false;
     841          89 :         Oid         relid = getrelid(rti, estate->es_range_table);
     842             : 
     843             :         /* If this is a result relation, already locked in InitPlan */
     844          89 :         foreach(l, stmt->nonleafResultRelations)
     845             :         {
     846           0 :             if (rti == lfirst_int(l))
     847             :             {
     848           0 :                 is_result_rel = true;
     849           0 :                 break;
     850             :             }
     851             :         }
     852             : 
     853             :         /*
     854             :          * Not a result relation; check if there is a RowMark that requires
     855             :          * taking a RowShareLock on this rel.
     856             :          */
     857          89 :         if (!is_result_rel)
     858             :         {
     859          89 :             PlanRowMark *rc = NULL;
     860             : 
     861          89 :             foreach(l, stmt->rowMarks)
     862             :             {
     863           0 :                 if (((PlanRowMark *) lfirst(l))->rti == rti)
     864             :                 {
     865           0 :                     rc = lfirst(l);
     866           0 :                     break;
     867             :                 }
     868             :             }
     869             : 
     870          89 :             if (rc && RowMarkRequiresRowShareLock(rc->markType))
     871           0 :                 LockRelationOid(relid, RowShareLock);
     872             :             else
     873          89 :                 LockRelationOid(relid, AccessShareLock);
     874             :         }
     875             :     }
     876         636 : }
     877             : 
     878             : /*
     879             :  *      GetAttributeByName
     880             :  *      GetAttributeByNum
     881             :  *
     882             :  *      These functions return the value of the requested attribute
     883             :  *      out of the given tuple Datum.
     884             :  *      C functions which take a tuple as an argument are expected
     885             :  *      to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
     886             :  *      Note: these are actually rather slow because they do a typcache
     887             :  *      lookup on each call.
     888             :  */
     889             : Datum
     890           6 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
     891             : {
     892             :     AttrNumber  attrno;
     893             :     Datum       result;
     894             :     Oid         tupType;
     895             :     int32       tupTypmod;
     896             :     TupleDesc   tupDesc;
     897             :     HeapTupleData tmptup;
     898             :     int         i;
     899             : 
     900           6 :     if (attname == NULL)
     901           0 :         elog(ERROR, "invalid attribute name");
     902             : 
     903           6 :     if (isNull == NULL)
     904           0 :         elog(ERROR, "a NULL isNull pointer was passed");
     905             : 
     906           6 :     if (tuple == NULL)
     907             :     {
     908             :         /* Kinda bogus but compatible with old behavior... */
     909           0 :         *isNull = true;
     910           0 :         return (Datum) 0;
     911             :     }
     912             : 
     913           6 :     tupType = HeapTupleHeaderGetTypeId(tuple);
     914           6 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
     915           6 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
     916             : 
     917           6 :     attrno = InvalidAttrNumber;
     918          24 :     for (i = 0; i < tupDesc->natts; i++)
     919             :     {
     920          24 :         Form_pg_attribute att = TupleDescAttr(tupDesc, i);
     921             : 
     922          24 :         if (namestrcmp(&(att->attname), attname) == 0)
     923             :         {
     924           6 :             attrno = att->attnum;
     925           6 :             break;
     926             :         }
     927             :     }
     928             : 
     929           6 :     if (attrno == InvalidAttrNumber)
     930           0 :         elog(ERROR, "attribute \"%s\" does not exist", attname);
     931             : 
     932             :     /*
     933             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
     934             :      * the fields in the struct just in case user tries to inspect system
     935             :      * columns.
     936             :      */
     937           6 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
     938           6 :     ItemPointerSetInvalid(&(tmptup.t_self));
     939           6 :     tmptup.t_tableOid = InvalidOid;
     940           6 :     tmptup.t_data = tuple;
     941             : 
     942           6 :     result = heap_getattr(&tmptup,
     943             :                           attrno,
     944             :                           tupDesc,
     945             :                           isNull);
     946             : 
     947           6 :     ReleaseTupleDesc(tupDesc);
     948             : 
     949           6 :     return result;
     950             : }
     951             : 
     952             : Datum
     953           0 : GetAttributeByNum(HeapTupleHeader tuple,
     954             :                   AttrNumber attrno,
     955             :                   bool *isNull)
     956             : {
     957             :     Datum       result;
     958             :     Oid         tupType;
     959             :     int32       tupTypmod;
     960             :     TupleDesc   tupDesc;
     961             :     HeapTupleData tmptup;
     962             : 
     963           0 :     if (!AttributeNumberIsValid(attrno))
     964           0 :         elog(ERROR, "invalid attribute number %d", attrno);
     965             : 
     966           0 :     if (isNull == NULL)
     967           0 :         elog(ERROR, "a NULL isNull pointer was passed");
     968             : 
     969           0 :     if (tuple == NULL)
     970             :     {
     971             :         /* Kinda bogus but compatible with old behavior... */
     972           0 :         *isNull = true;
     973           0 :         return (Datum) 0;
     974             :     }
     975             : 
     976           0 :     tupType = HeapTupleHeaderGetTypeId(tuple);
     977           0 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
     978           0 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
     979             : 
     980             :     /*
     981             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
     982             :      * the fields in the struct just in case user tries to inspect system
     983             :      * columns.
     984             :      */
     985           0 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
     986           0 :     ItemPointerSetInvalid(&(tmptup.t_self));
     987           0 :     tmptup.t_tableOid = InvalidOid;
     988           0 :     tmptup.t_data = tuple;
     989             : 
     990           0 :     result = heap_getattr(&tmptup,
     991             :                           attrno,
     992             :                           tupDesc,
     993             :                           isNull);
     994             : 
     995           0 :     ReleaseTupleDesc(tupDesc);
     996             : 
     997           0 :     return result;
     998             : }
     999             : 
    1000             : /*
    1001             :  * Number of items in a tlist (including any resjunk items!)
    1002             :  */
    1003             : int
    1004       54990 : ExecTargetListLength(List *targetlist)
    1005             : {
    1006             :     /* This used to be more complex, but fjoins are dead */
    1007       54990 :     return list_length(targetlist);
    1008             : }
    1009             : 
    1010             : /*
    1011             :  * Number of items in a tlist, not including any resjunk items
    1012             :  */
    1013             : int
    1014       13310 : ExecCleanTargetListLength(List *targetlist)
    1015             : {
    1016       13310 :     int         len = 0;
    1017             :     ListCell   *tl;
    1018             : 
    1019       32004 :     foreach(tl, targetlist)
    1020             :     {
    1021       18694 :         TargetEntry *curTle = lfirst_node(TargetEntry, tl);
    1022             : 
    1023       18694 :         if (!curTle->resjunk)
    1024       16284 :             len++;
    1025             :     }
    1026       13310 :     return len;
    1027             : }

Generated by: LCOV version 1.11