LCOV - code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 339 385 88.1 %
Date: 2021-12-03 04:09:03 Functions: 37 40 92.5 %
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-2021, 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             :  *      etc
      26             :  *
      27             :  *      ExecOpenScanRelation    Common code for scan node init routines.
      28             :  *
      29             :  *      ExecInitRangeTable      Set up executor's range-table-related data.
      30             :  *
      31             :  *      ExecGetRangeTableRelation       Fetch Relation for a rangetable entry.
      32             :  *
      33             :  *      executor_errposition    Report syntactic position of an error.
      34             :  *
      35             :  *      RegisterExprContextCallback    Register function shutdown callback
      36             :  *      UnregisterExprContextCallback  Deregister function shutdown callback
      37             :  *
      38             :  *      GetAttributeByName      Runtime extraction of columns from tuples.
      39             :  *      GetAttributeByNum
      40             :  *
      41             :  *   NOTES
      42             :  *      This file has traditionally been the place to stick misc.
      43             :  *      executor support stuff that doesn't really go anyplace else.
      44             :  */
      45             : 
      46             : #include "postgres.h"
      47             : 
      48             : #include "access/parallel.h"
      49             : #include "access/relscan.h"
      50             : #include "access/table.h"
      51             : #include "access/tableam.h"
      52             : #include "access/transam.h"
      53             : #include "executor/executor.h"
      54             : #include "executor/execPartition.h"
      55             : #include "jit/jit.h"
      56             : #include "mb/pg_wchar.h"
      57             : #include "miscadmin.h"
      58             : #include "nodes/nodeFuncs.h"
      59             : #include "parser/parsetree.h"
      60             : #include "partitioning/partdesc.h"
      61             : #include "storage/lmgr.h"
      62             : #include "utils/builtins.h"
      63             : #include "utils/memutils.h"
      64             : #include "utils/rel.h"
      65             : #include "utils/typcache.h"
      66             : 
      67             : 
      68             : static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc);
      69             : static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
      70             : 
      71             : 
      72             : /* ----------------------------------------------------------------
      73             :  *               Executor state and memory management functions
      74             :  * ----------------------------------------------------------------
      75             :  */
      76             : 
      77             : /* ----------------
      78             :  *      CreateExecutorState
      79             :  *
      80             :  *      Create and initialize an EState node, which is the root of
      81             :  *      working storage for an entire Executor invocation.
      82             :  *
      83             :  * Principally, this creates the per-query memory context that will be
      84             :  * used to hold all working data that lives till the end of the query.
      85             :  * Note that the per-query context will become a child of the caller's
      86             :  * CurrentMemoryContext.
      87             :  * ----------------
      88             :  */
      89             : EState *
      90     1004896 : CreateExecutorState(void)
      91             : {
      92             :     EState     *estate;
      93             :     MemoryContext qcontext;
      94             :     MemoryContext oldcontext;
      95             : 
      96             :     /*
      97             :      * Create the per-query context for this Executor run.
      98             :      */
      99     1004896 :     qcontext = AllocSetContextCreate(CurrentMemoryContext,
     100             :                                      "ExecutorState",
     101             :                                      ALLOCSET_DEFAULT_SIZES);
     102             : 
     103             :     /*
     104             :      * Make the EState node within the per-query context.  This way, we don't
     105             :      * need a separate pfree() operation for it at shutdown.
     106             :      */
     107     1004896 :     oldcontext = MemoryContextSwitchTo(qcontext);
     108             : 
     109     1004896 :     estate = makeNode(EState);
     110             : 
     111             :     /*
     112             :      * Initialize all fields of the Executor State structure
     113             :      */
     114     1004896 :     estate->es_direction = ForwardScanDirection;
     115     1004896 :     estate->es_snapshot = InvalidSnapshot;   /* caller must initialize this */
     116     1004896 :     estate->es_crosscheck_snapshot = InvalidSnapshot;    /* no crosscheck */
     117     1004896 :     estate->es_range_table = NIL;
     118     1004896 :     estate->es_range_table_size = 0;
     119     1004896 :     estate->es_relations = NULL;
     120     1004896 :     estate->es_rowmarks = NULL;
     121     1004896 :     estate->es_plannedstmt = NULL;
     122             : 
     123     1004896 :     estate->es_junkFilter = NULL;
     124             : 
     125     1004896 :     estate->es_output_cid = (CommandId) 0;
     126             : 
     127     1004896 :     estate->es_result_relations = NULL;
     128     1004896 :     estate->es_opened_result_relations = NIL;
     129     1004896 :     estate->es_tuple_routing_result_relations = NIL;
     130     1004896 :     estate->es_trig_target_relations = NIL;
     131             : 
     132     1004896 :     estate->es_param_list_info = NULL;
     133     1004896 :     estate->es_param_exec_vals = NULL;
     134             : 
     135     1004896 :     estate->es_queryEnv = NULL;
     136             : 
     137     1004896 :     estate->es_query_cxt = qcontext;
     138             : 
     139     1004896 :     estate->es_tupleTable = NIL;
     140             : 
     141     1004896 :     estate->es_processed = 0;
     142             : 
     143     1004896 :     estate->es_top_eflags = 0;
     144     1004896 :     estate->es_instrument = 0;
     145     1004896 :     estate->es_finished = false;
     146             : 
     147     1004896 :     estate->es_exprcontexts = NIL;
     148             : 
     149     1004896 :     estate->es_subplanstates = NIL;
     150             : 
     151     1004896 :     estate->es_auxmodifytables = NIL;
     152             : 
     153     1004896 :     estate->es_per_tuple_exprcontext = NULL;
     154             : 
     155     1004896 :     estate->es_sourceText = NULL;
     156             : 
     157     1004896 :     estate->es_use_parallel_mode = false;
     158             : 
     159     1004896 :     estate->es_jit_flags = 0;
     160     1004896 :     estate->es_jit = NULL;
     161             : 
     162             :     /*
     163             :      * Return the executor state structure
     164             :      */
     165     1004896 :     MemoryContextSwitchTo(oldcontext);
     166             : 
     167     1004896 :     return estate;
     168             : }
     169             : 
     170             : /* ----------------
     171             :  *      FreeExecutorState
     172             :  *
     173             :  *      Release an EState along with all remaining working storage.
     174             :  *
     175             :  * Note: this is not responsible for releasing non-memory resources, such as
     176             :  * open relations or buffer pins.  But it will shut down any still-active
     177             :  * ExprContexts within the EState and deallocate associated JITed expressions.
     178             :  * That is sufficient cleanup for situations where the EState has only been
     179             :  * used for expression evaluation, and not to run a complete Plan.
     180             :  *
     181             :  * This can be called in any memory context ... so long as it's not one
     182             :  * of the ones to be freed.
     183             :  * ----------------
     184             :  */
     185             : void
     186      985760 : FreeExecutorState(EState *estate)
     187             : {
     188             :     /*
     189             :      * Shut down and free any remaining ExprContexts.  We do this explicitly
     190             :      * to ensure that any remaining shutdown callbacks get called (since they
     191             :      * might need to release resources that aren't simply memory within the
     192             :      * per-query memory context).
     193             :      */
     194     2750516 :     while (estate->es_exprcontexts)
     195             :     {
     196             :         /*
     197             :          * XXX: seems there ought to be a faster way to implement this than
     198             :          * repeated list_delete(), no?
     199             :          */
     200     1764756 :         FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
     201             :                         true);
     202             :         /* FreeExprContext removed the list link for us */
     203             :     }
     204             : 
     205             :     /* release JIT context, if allocated */
     206      985760 :     if (estate->es_jit)
     207             :     {
     208        1076 :         jit_release_context(estate->es_jit);
     209        1076 :         estate->es_jit = NULL;
     210             :     }
     211             : 
     212             :     /* release partition directory, if allocated */
     213      985760 :     if (estate->es_partition_directory)
     214             :     {
     215        2588 :         DestroyPartitionDirectory(estate->es_partition_directory);
     216        2588 :         estate->es_partition_directory = NULL;
     217             :     }
     218             : 
     219             :     /*
     220             :      * Free the per-query memory context, thereby releasing all working
     221             :      * memory, including the EState node itself.
     222             :      */
     223      985760 :     MemoryContextDelete(estate->es_query_cxt);
     224      985760 : }
     225             : 
     226             : /*
     227             :  * Internal implementation for CreateExprContext() and CreateWorkExprContext()
     228             :  * that allows control over the AllocSet parameters.
     229             :  */
     230             : static ExprContext *
     231     1843346 : CreateExprContextInternal(EState *estate, Size minContextSize,
     232             :                           Size initBlockSize, Size maxBlockSize)
     233             : {
     234             :     ExprContext *econtext;
     235             :     MemoryContext oldcontext;
     236             : 
     237             :     /* Create the ExprContext node within the per-query memory context */
     238     1843346 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     239             : 
     240     1843346 :     econtext = makeNode(ExprContext);
     241             : 
     242             :     /* Initialize fields of ExprContext */
     243     1843346 :     econtext->ecxt_scantuple = NULL;
     244     1843346 :     econtext->ecxt_innertuple = NULL;
     245     1843346 :     econtext->ecxt_outertuple = NULL;
     246             : 
     247     1843346 :     econtext->ecxt_per_query_memory = estate->es_query_cxt;
     248             : 
     249             :     /*
     250             :      * Create working memory for expression evaluation in this context.
     251             :      */
     252     1843346 :     econtext->ecxt_per_tuple_memory =
     253     1843346 :         AllocSetContextCreate(estate->es_query_cxt,
     254             :                               "ExprContext",
     255             :                               minContextSize,
     256             :                               initBlockSize,
     257             :                               maxBlockSize);
     258             : 
     259     1843346 :     econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
     260     1843346 :     econtext->ecxt_param_list_info = estate->es_param_list_info;
     261             : 
     262     1843346 :     econtext->ecxt_aggvalues = NULL;
     263     1843346 :     econtext->ecxt_aggnulls = NULL;
     264             : 
     265     1843346 :     econtext->caseValue_datum = (Datum) 0;
     266     1843346 :     econtext->caseValue_isNull = true;
     267             : 
     268     1843346 :     econtext->domainValue_datum = (Datum) 0;
     269     1843346 :     econtext->domainValue_isNull = true;
     270             : 
     271     1843346 :     econtext->ecxt_estate = estate;
     272             : 
     273     1843346 :     econtext->ecxt_callbacks = NULL;
     274             : 
     275             :     /*
     276             :      * Link the ExprContext into the EState to ensure it is shut down when the
     277             :      * EState is freed.  Because we use lcons(), shutdowns will occur in
     278             :      * reverse order of creation, which may not be essential but can't hurt.
     279             :      */
     280     1843346 :     estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
     281             : 
     282     1843346 :     MemoryContextSwitchTo(oldcontext);
     283             : 
     284     1843346 :     return econtext;
     285             : }
     286             : 
     287             : /* ----------------
     288             :  *      CreateExprContext
     289             :  *
     290             :  *      Create a context for expression evaluation within an EState.
     291             :  *
     292             :  * An executor run may require multiple ExprContexts (we usually make one
     293             :  * for each Plan node, and a separate one for per-output-tuple processing
     294             :  * such as constraint checking).  Each ExprContext has its own "per-tuple"
     295             :  * memory context.
     296             :  *
     297             :  * Note we make no assumption about the caller's memory context.
     298             :  * ----------------
     299             :  */
     300             : ExprContext *
     301     1838308 : CreateExprContext(EState *estate)
     302             : {
     303     1838308 :     return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES);
     304             : }
     305             : 
     306             : 
     307             : /* ----------------
     308             :  *      CreateWorkExprContext
     309             :  *
     310             :  * Like CreateExprContext, but specifies the AllocSet sizes to be reasonable
     311             :  * in proportion to work_mem. If the maximum block allocation size is too
     312             :  * large, it's easy to skip right past work_mem with a single allocation.
     313             :  * ----------------
     314             :  */
     315             : ExprContext *
     316        5038 : CreateWorkExprContext(EState *estate)
     317             : {
     318        5038 :     Size        minContextSize = ALLOCSET_DEFAULT_MINSIZE;
     319        5038 :     Size        initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
     320        5038 :     Size        maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
     321             : 
     322             :     /* choose the maxBlockSize to be no larger than 1/16 of work_mem */
     323       30588 :     while (16 * maxBlockSize > work_mem * 1024L)
     324       25550 :         maxBlockSize >>= 1;
     325             : 
     326        5038 :     if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
     327          52 :         maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
     328             : 
     329        5038 :     return CreateExprContextInternal(estate, minContextSize,
     330             :                                      initBlockSize, maxBlockSize);
     331             : }
     332             : 
     333             : /* ----------------
     334             :  *      CreateStandaloneExprContext
     335             :  *
     336             :  *      Create a context for standalone expression evaluation.
     337             :  *
     338             :  * An ExprContext made this way can be used for evaluation of expressions
     339             :  * that contain no Params, subplans, or Var references (it might work to
     340             :  * put tuple references into the scantuple field, but it seems unwise).
     341             :  *
     342             :  * The ExprContext struct is allocated in the caller's current memory
     343             :  * context, which also becomes its "per query" context.
     344             :  *
     345             :  * It is caller's responsibility to free the ExprContext when done,
     346             :  * or at least ensure that any shutdown callbacks have been called
     347             :  * (ReScanExprContext() is suitable).  Otherwise, non-memory resources
     348             :  * might be leaked.
     349             :  * ----------------
     350             :  */
     351             : ExprContext *
     352        7640 : CreateStandaloneExprContext(void)
     353             : {
     354             :     ExprContext *econtext;
     355             : 
     356             :     /* Create the ExprContext node within the caller's memory context */
     357        7640 :     econtext = makeNode(ExprContext);
     358             : 
     359             :     /* Initialize fields of ExprContext */
     360        7640 :     econtext->ecxt_scantuple = NULL;
     361        7640 :     econtext->ecxt_innertuple = NULL;
     362        7640 :     econtext->ecxt_outertuple = NULL;
     363             : 
     364        7640 :     econtext->ecxt_per_query_memory = CurrentMemoryContext;
     365             : 
     366             :     /*
     367             :      * Create working memory for expression evaluation in this context.
     368             :      */
     369        7640 :     econtext->ecxt_per_tuple_memory =
     370        7640 :         AllocSetContextCreate(CurrentMemoryContext,
     371             :                               "ExprContext",
     372             :                               ALLOCSET_DEFAULT_SIZES);
     373             : 
     374        7640 :     econtext->ecxt_param_exec_vals = NULL;
     375        7640 :     econtext->ecxt_param_list_info = NULL;
     376             : 
     377        7640 :     econtext->ecxt_aggvalues = NULL;
     378        7640 :     econtext->ecxt_aggnulls = NULL;
     379             : 
     380        7640 :     econtext->caseValue_datum = (Datum) 0;
     381        7640 :     econtext->caseValue_isNull = true;
     382             : 
     383        7640 :     econtext->domainValue_datum = (Datum) 0;
     384        7640 :     econtext->domainValue_isNull = true;
     385             : 
     386        7640 :     econtext->ecxt_estate = NULL;
     387             : 
     388        7640 :     econtext->ecxt_callbacks = NULL;
     389             : 
     390        7640 :     return econtext;
     391             : }
     392             : 
     393             : /* ----------------
     394             :  *      FreeExprContext
     395             :  *
     396             :  *      Free an expression context, including calling any remaining
     397             :  *      shutdown callbacks.
     398             :  *
     399             :  * Since we free the temporary context used for expression evaluation,
     400             :  * any previously computed pass-by-reference expression result will go away!
     401             :  *
     402             :  * If isCommit is false, we are being called in error cleanup, and should
     403             :  * not call callbacks but only release memory.  (It might be better to call
     404             :  * the callbacks and pass the isCommit flag to them, but that would require
     405             :  * more invasive code changes than currently seems justified.)
     406             :  *
     407             :  * Note we make no assumption about the caller's memory context.
     408             :  * ----------------
     409             :  */
     410             : void
     411     1821094 : FreeExprContext(ExprContext *econtext, bool isCommit)
     412             : {
     413             :     EState     *estate;
     414             : 
     415             :     /* Call any registered callbacks */
     416     1821094 :     ShutdownExprContext(econtext, isCommit);
     417             :     /* And clean up the memory used */
     418     1821094 :     MemoryContextDelete(econtext->ecxt_per_tuple_memory);
     419             :     /* Unlink self from owning EState, if any */
     420     1821094 :     estate = econtext->ecxt_estate;
     421     1821094 :     if (estate)
     422     1821094 :         estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
     423             :                                                   econtext);
     424             :     /* And delete the ExprContext node */
     425     1821094 :     pfree(econtext);
     426     1821094 : }
     427             : 
     428             : /*
     429             :  * ReScanExprContext
     430             :  *
     431             :  *      Reset an expression context in preparation for a rescan of its
     432             :  *      plan node.  This requires calling any registered shutdown callbacks,
     433             :  *      since any partially complete set-returning-functions must be canceled.
     434             :  *
     435             :  * Note we make no assumption about the caller's memory context.
     436             :  */
     437             : void
     438    12992622 : ReScanExprContext(ExprContext *econtext)
     439             : {
     440             :     /* Call any registered callbacks */
     441    12992622 :     ShutdownExprContext(econtext, true);
     442             :     /* And clean up the memory used */
     443    12992622 :     MemoryContextReset(econtext->ecxt_per_tuple_memory);
     444    12992622 : }
     445             : 
     446             : /*
     447             :  * Build a per-output-tuple ExprContext for an EState.
     448             :  *
     449             :  * This is normally invoked via GetPerTupleExprContext() macro,
     450             :  * not directly.
     451             :  */
     452             : ExprContext *
     453      572734 : MakePerTupleExprContext(EState *estate)
     454             : {
     455      572734 :     if (estate->es_per_tuple_exprcontext == NULL)
     456      572734 :         estate->es_per_tuple_exprcontext = CreateExprContext(estate);
     457             : 
     458      572734 :     return estate->es_per_tuple_exprcontext;
     459             : }
     460             : 
     461             : 
     462             : /* ----------------------------------------------------------------
     463             :  *               miscellaneous node-init support functions
     464             :  *
     465             :  * Note: all of these are expected to be called with CurrentMemoryContext
     466             :  * equal to the per-query memory context.
     467             :  * ----------------------------------------------------------------
     468             :  */
     469             : 
     470             : /* ----------------
     471             :  *      ExecAssignExprContext
     472             :  *
     473             :  *      This initializes the ps_ExprContext field.  It is only necessary
     474             :  *      to do this for nodes which use ExecQual or ExecProject
     475             :  *      because those routines require an econtext. Other nodes that
     476             :  *      don't have to evaluate expressions don't need to do this.
     477             :  * ----------------
     478             :  */
     479             : void
     480     1197558 : ExecAssignExprContext(EState *estate, PlanState *planstate)
     481             : {
     482     1197558 :     planstate->ps_ExprContext = CreateExprContext(estate);
     483     1197558 : }
     484             : 
     485             : /* ----------------
     486             :  *      ExecGetResultType
     487             :  * ----------------
     488             :  */
     489             : TupleDesc
     490     1819902 : ExecGetResultType(PlanState *planstate)
     491             : {
     492     1819902 :     return planstate->ps_ResultTupleDesc;
     493             : }
     494             : 
     495             : /*
     496             :  * ExecGetResultSlotOps - information about node's type of result slot
     497             :  */
     498             : const TupleTableSlotOps *
     499      765888 : ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
     500             : {
     501      765888 :     if (planstate->resultopsset && planstate->resultops)
     502             :     {
     503      764962 :         if (isfixed)
     504      712852 :             *isfixed = planstate->resultopsfixed;
     505      764962 :         return planstate->resultops;
     506             :     }
     507             : 
     508         926 :     if (isfixed)
     509             :     {
     510         902 :         if (planstate->resultopsset)
     511         902 :             *isfixed = planstate->resultopsfixed;
     512           0 :         else if (planstate->ps_ResultTupleSlot)
     513           0 :             *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
     514             :         else
     515           0 :             *isfixed = false;
     516             :     }
     517             : 
     518         926 :     if (!planstate->ps_ResultTupleSlot)
     519         926 :         return &TTSOpsVirtual;
     520             : 
     521           0 :     return planstate->ps_ResultTupleSlot->tts_ops;
     522             : }
     523             : 
     524             : 
     525             : /* ----------------
     526             :  *      ExecAssignProjectionInfo
     527             :  *
     528             :  * forms the projection information from the node's targetlist
     529             :  *
     530             :  * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
     531             :  * for a relation-scan node, can pass NULL for upper-level nodes
     532             :  * ----------------
     533             :  */
     534             : void
     535      677826 : ExecAssignProjectionInfo(PlanState *planstate,
     536             :                          TupleDesc inputDesc)
     537             : {
     538      677766 :     planstate->ps_ProjInfo =
     539      677826 :         ExecBuildProjectionInfo(planstate->plan->targetlist,
     540             :                                 planstate->ps_ExprContext,
     541             :                                 planstate->ps_ResultTupleSlot,
     542             :                                 planstate,
     543             :                                 inputDesc);
     544      677766 : }
     545             : 
     546             : 
     547             : /* ----------------
     548             :  *      ExecConditionalAssignProjectionInfo
     549             :  *
     550             :  * as ExecAssignProjectionInfo, but store NULL rather than building projection
     551             :  * info if no projection is required
     552             :  * ----------------
     553             :  */
     554             : void
     555      482026 : ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
     556             :                                     int varno)
     557             : {
     558      482026 :     if (tlist_matches_tupdesc(planstate,
     559      482026 :                               planstate->plan->targetlist,
     560             :                               varno,
     561             :                               inputDesc))
     562             :     {
     563      251490 :         planstate->ps_ProjInfo = NULL;
     564      251490 :         planstate->resultopsset = planstate->scanopsset;
     565      251490 :         planstate->resultopsfixed = planstate->scanopsfixed;
     566      251490 :         planstate->resultops = planstate->scanops;
     567             :     }
     568             :     else
     569             :     {
     570      230536 :         if (!planstate->ps_ResultTupleSlot)
     571             :         {
     572      230536 :             ExecInitResultSlot(planstate, &TTSOpsVirtual);
     573      230536 :             planstate->resultops = &TTSOpsVirtual;
     574      230536 :             planstate->resultopsfixed = true;
     575      230536 :             planstate->resultopsset = true;
     576             :         }
     577      230536 :         ExecAssignProjectionInfo(planstate, inputDesc);
     578             :     }
     579      482026 : }
     580             : 
     581             : static bool
     582      482026 : tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
     583             : {
     584      482026 :     int         numattrs = tupdesc->natts;
     585             :     int         attrno;
     586      482026 :     ListCell   *tlist_item = list_head(tlist);
     587             : 
     588             :     /* Check the tlist attributes */
     589     4544748 :     for (attrno = 1; attrno <= numattrs; attrno++)
     590             :     {
     591     4284242 :         Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
     592             :         Var        *var;
     593             : 
     594     4284242 :         if (tlist_item == NULL)
     595       23484 :             return false;       /* tlist too short */
     596     4260758 :         var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
     597     4260758 :         if (!var || !IsA(var, Var))
     598       65848 :             return false;       /* tlist item not a Var */
     599             :         /* if these Asserts fail, planner messed up */
     600             :         Assert(var->varno == varno);
     601             :         Assert(var->varlevelsup == 0);
     602     4194910 :         if (var->varattno != attrno)
     603      132004 :             return false;       /* out of order */
     604     4062906 :         if (att_tup->attisdropped)
     605           0 :             return false;       /* table contains dropped columns */
     606     4062906 :         if (att_tup->atthasmissing)
     607         180 :             return false;       /* table contains cols with missing values */
     608             : 
     609             :         /*
     610             :          * Note: usually the Var's type should match the tupdesc exactly, but
     611             :          * in situations involving unions of columns that have different
     612             :          * typmods, the Var may have come from above the union and hence have
     613             :          * typmod -1.  This is a legitimate situation since the Var still
     614             :          * describes the column, just not as exactly as the tupdesc does. We
     615             :          * could change the planner to prevent it, but it'd then insert
     616             :          * projection steps just to convert from specific typmod to typmod -1,
     617             :          * which is pretty silly.
     618             :          */
     619     4062726 :         if (var->vartype != att_tup->atttypid ||
     620     4062722 :             (var->vartypmod != att_tup->atttypmod &&
     621           4 :              var->vartypmod != -1))
     622           4 :             return false;       /* type mismatch */
     623             : 
     624     4062722 :         tlist_item = lnext(tlist, tlist_item);
     625             :     }
     626             : 
     627      260506 :     if (tlist_item)
     628        9016 :         return false;           /* tlist too long */
     629             : 
     630      251490 :     return true;
     631             : }
     632             : 
     633             : /* ----------------
     634             :  *      ExecFreeExprContext
     635             :  *
     636             :  * A plan node's ExprContext should be freed explicitly during executor
     637             :  * shutdown because there may be shutdown callbacks to call.  (Other resources
     638             :  * made by the above routines, such as projection info, don't need to be freed
     639             :  * explicitly because they're just memory in the per-query memory context.)
     640             :  *
     641             :  * However ... there is no particular need to do it during ExecEndNode,
     642             :  * because FreeExecutorState will free any remaining ExprContexts within
     643             :  * the EState.  Letting FreeExecutorState do it allows the ExprContexts to
     644             :  * be freed in reverse order of creation, rather than order of creation as
     645             :  * will happen if we delete them here, which saves O(N^2) work in the list
     646             :  * cleanup inside FreeExprContext.
     647             :  * ----------------
     648             :  */
     649             : void
     650      889900 : ExecFreeExprContext(PlanState *planstate)
     651             : {
     652             :     /*
     653             :      * Per above discussion, don't actually delete the ExprContext. We do
     654             :      * unlink it from the plan node, though.
     655             :      */
     656      889900 :     planstate->ps_ExprContext = NULL;
     657      889900 : }
     658             : 
     659             : 
     660             : /* ----------------------------------------------------------------
     661             :  *                Scan node support
     662             :  * ----------------------------------------------------------------
     663             :  */
     664             : 
     665             : /* ----------------
     666             :  *      ExecAssignScanType
     667             :  * ----------------
     668             :  */
     669             : void
     670         430 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
     671             : {
     672         430 :     TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
     673             : 
     674         430 :     ExecSetSlotDescriptor(slot, tupDesc);
     675         430 : }
     676             : 
     677             : /* ----------------
     678             :  *      ExecCreateScanSlotFromOuterPlan
     679             :  * ----------------
     680             :  */
     681             : void
     682      155968 : ExecCreateScanSlotFromOuterPlan(EState *estate,
     683             :                                 ScanState *scanstate,
     684             :                                 const TupleTableSlotOps *tts_ops)
     685             : {
     686             :     PlanState  *outerPlan;
     687             :     TupleDesc   tupDesc;
     688             : 
     689      155968 :     outerPlan = outerPlanState(scanstate);
     690      155968 :     tupDesc = ExecGetResultType(outerPlan);
     691             : 
     692      155968 :     ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
     693      155968 : }
     694             : 
     695             : /* ----------------------------------------------------------------
     696             :  *      ExecRelationIsTargetRelation
     697             :  *
     698             :  *      Detect whether a relation (identified by rangetable index)
     699             :  *      is one of the target relations of the query.
     700             :  *
     701             :  * Note: This is currently no longer used in core.  We keep it around
     702             :  * because FDWs may wish to use it to determine if their foreign table
     703             :  * is a target relation.
     704             :  * ----------------------------------------------------------------
     705             :  */
     706             : bool
     707           0 : ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
     708             : {
     709           0 :     return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
     710             : }
     711             : 
     712             : /* ----------------------------------------------------------------
     713             :  *      ExecOpenScanRelation
     714             :  *
     715             :  *      Open the heap relation to be scanned by a base-level scan plan node.
     716             :  *      This should be called during the node's ExecInit routine.
     717             :  * ----------------------------------------------------------------
     718             :  */
     719             : Relation
     720      391176 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
     721             : {
     722             :     Relation    rel;
     723             : 
     724             :     /* Open the relation. */
     725      391176 :     rel = ExecGetRangeTableRelation(estate, scanrelid);
     726             : 
     727             :     /*
     728             :      * Complain if we're attempting a scan of an unscannable relation, except
     729             :      * when the query won't actually be run.  This is a slightly klugy place
     730             :      * to do this, perhaps, but there is no better place.
     731             :      */
     732      391176 :     if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
     733      373142 :         !RelationIsScannable(rel))
     734           8 :         ereport(ERROR,
     735             :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
     736             :                  errmsg("materialized view \"%s\" has not been populated",
     737             :                         RelationGetRelationName(rel)),
     738             :                  errhint("Use the REFRESH MATERIALIZED VIEW command.")));
     739             : 
     740      391168 :     return rel;
     741             : }
     742             : 
     743             : /*
     744             :  * ExecInitRangeTable
     745             :  *      Set up executor's range-table-related data
     746             :  *
     747             :  * In addition to the range table proper, initialize arrays that are
     748             :  * indexed by rangetable index.
     749             :  */
     750             : void
     751      667210 : ExecInitRangeTable(EState *estate, List *rangeTable)
     752             : {
     753             :     /* Remember the range table List as-is */
     754      667210 :     estate->es_range_table = rangeTable;
     755             : 
     756             :     /* Set size of associated arrays */
     757      667210 :     estate->es_range_table_size = list_length(rangeTable);
     758             : 
     759             :     /*
     760             :      * Allocate an array to store an open Relation corresponding to each
     761             :      * rangetable entry, and initialize entries to NULL.  Relations are opened
     762             :      * and stored here as needed.
     763             :      */
     764      667210 :     estate->es_relations = (Relation *)
     765      667210 :         palloc0(estate->es_range_table_size * sizeof(Relation));
     766             : 
     767             :     /*
     768             :      * es_result_relations and es_rowmarks are also parallel to
     769             :      * es_range_table, but are allocated only if needed.
     770             :      */
     771      667210 :     estate->es_result_relations = NULL;
     772      667210 :     estate->es_rowmarks = NULL;
     773      667210 : }
     774             : 
     775             : /*
     776             :  * ExecGetRangeTableRelation
     777             :  *      Open the Relation for a range table entry, if not already done
     778             :  *
     779             :  * The Relations will be closed again in ExecEndPlan().
     780             :  */
     781             : Relation
     782      501822 : ExecGetRangeTableRelation(EState *estate, Index rti)
     783             : {
     784             :     Relation    rel;
     785             : 
     786             :     Assert(rti > 0 && rti <= estate->es_range_table_size);
     787             : 
     788      501822 :     rel = estate->es_relations[rti - 1];
     789      501822 :     if (rel == NULL)
     790             :     {
     791             :         /* First time through, so open the relation */
     792      472586 :         RangeTblEntry *rte = exec_rt_fetch(rti, estate);
     793             : 
     794             :         Assert(rte->rtekind == RTE_RELATION);
     795             : 
     796      472586 :         if (!IsParallelWorker())
     797             :         {
     798             :             /*
     799             :              * In a normal query, we should already have the appropriate lock,
     800             :              * but verify that through an Assert.  Since there's already an
     801             :              * Assert inside table_open that insists on holding some lock, it
     802             :              * seems sufficient to check this only when rellockmode is higher
     803             :              * than the minimum.
     804             :              */
     805      469626 :             rel = table_open(rte->relid, NoLock);
     806             :             Assert(rte->rellockmode == AccessShareLock ||
     807             :                    CheckRelationLockedByMe(rel, rte->rellockmode, false));
     808             :         }
     809             :         else
     810             :         {
     811             :             /*
     812             :              * If we are a parallel worker, we need to obtain our own local
     813             :              * lock on the relation.  This ensures sane behavior in case the
     814             :              * parent process exits before we do.
     815             :              */
     816        2960 :             rel = table_open(rte->relid, rte->rellockmode);
     817             :         }
     818             : 
     819      472586 :         estate->es_relations[rti - 1] = rel;
     820             :     }
     821             : 
     822      501822 :     return rel;
     823             : }
     824             : 
     825             : /*
     826             :  * ExecInitResultRelation
     827             :  *      Open relation given by the passed-in RT index and fill its
     828             :  *      ResultRelInfo node
     829             :  *
     830             :  * Here, we also save the ResultRelInfo in estate->es_result_relations array
     831             :  * such that it can be accessed later using the RT index.
     832             :  */
     833             : void
     834      103338 : ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
     835             :                        Index rti)
     836             : {
     837             :     Relation    resultRelationDesc;
     838             : 
     839      103338 :     resultRelationDesc = ExecGetRangeTableRelation(estate, rti);
     840      103338 :     InitResultRelInfo(resultRelInfo,
     841             :                       resultRelationDesc,
     842             :                       rti,
     843             :                       NULL,
     844             :                       estate->es_instrument);
     845             : 
     846      103338 :     if (estate->es_result_relations == NULL)
     847       98686 :         estate->es_result_relations = (ResultRelInfo **)
     848       98686 :             palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
     849      103338 :     estate->es_result_relations[rti - 1] = resultRelInfo;
     850             : 
     851             :     /*
     852             :      * Saving in the list allows to avoid needlessly traversing the whole
     853             :      * array when only a few of its entries are possibly non-NULL.
     854             :      */
     855      103338 :     estate->es_opened_result_relations =
     856      103338 :         lappend(estate->es_opened_result_relations, resultRelInfo);
     857      103338 : }
     858             : 
     859             : /*
     860             :  * UpdateChangedParamSet
     861             :  *      Add changed parameters to a plan node's chgParam set
     862             :  */
     863             : void
     864     5604874 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
     865             : {
     866             :     Bitmapset  *parmset;
     867             : 
     868             :     /*
     869             :      * The plan node only depends on params listed in its allParam set. Don't
     870             :      * include anything else into its chgParam set.
     871             :      */
     872     5604874 :     parmset = bms_intersect(node->plan->allParam, newchg);
     873             : 
     874             :     /*
     875             :      * Keep node->chgParam == NULL if there's not actually any members; this
     876             :      * allows the simplest possible tests in executor node files.
     877             :      */
     878     5604874 :     if (!bms_is_empty(parmset))
     879     5481814 :         node->chgParam = bms_join(node->chgParam, parmset);
     880             :     else
     881      123060 :         bms_free(parmset);
     882     5604874 : }
     883             : 
     884             : /*
     885             :  * executor_errposition
     886             :  *      Report an execution-time cursor position, if possible.
     887             :  *
     888             :  * This is expected to be used within an ereport() call.  The return value
     889             :  * is a dummy (always 0, in fact).
     890             :  *
     891             :  * The locations stored in parsetrees are byte offsets into the source string.
     892             :  * We have to convert them to 1-based character indexes for reporting to
     893             :  * clients.  (We do things this way to avoid unnecessary overhead in the
     894             :  * normal non-error case: computing character indexes would be much more
     895             :  * expensive than storing token offsets.)
     896             :  */
     897             : int
     898           0 : executor_errposition(EState *estate, int location)
     899             : {
     900             :     int         pos;
     901             : 
     902             :     /* No-op if location was not provided */
     903           0 :     if (location < 0)
     904           0 :         return 0;
     905             :     /* Can't do anything if source text is not available */
     906           0 :     if (estate == NULL || estate->es_sourceText == NULL)
     907           0 :         return 0;
     908             :     /* Convert offset to character number */
     909           0 :     pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
     910             :     /* And pass it to the ereport mechanism */
     911           0 :     return errposition(pos);
     912             : }
     913             : 
     914             : /*
     915             :  * Register a shutdown callback in an ExprContext.
     916             :  *
     917             :  * Shutdown callbacks will be called (in reverse order of registration)
     918             :  * when the ExprContext is deleted or rescanned.  This provides a hook
     919             :  * for functions called in the context to do any cleanup needed --- it's
     920             :  * particularly useful for functions returning sets.  Note that the
     921             :  * callback will *not* be called in the event that execution is aborted
     922             :  * by an error.
     923             :  */
     924             : void
     925     1905812 : RegisterExprContextCallback(ExprContext *econtext,
     926             :                             ExprContextCallbackFunction function,
     927             :                             Datum arg)
     928             : {
     929             :     ExprContext_CB *ecxt_callback;
     930             : 
     931             :     /* Save the info in appropriate memory context */
     932             :     ecxt_callback = (ExprContext_CB *)
     933     1905812 :         MemoryContextAlloc(econtext->ecxt_per_query_memory,
     934             :                            sizeof(ExprContext_CB));
     935             : 
     936     1905812 :     ecxt_callback->function = function;
     937     1905812 :     ecxt_callback->arg = arg;
     938             : 
     939             :     /* link to front of list for appropriate execution order */
     940     1905812 :     ecxt_callback->next = econtext->ecxt_callbacks;
     941     1905812 :     econtext->ecxt_callbacks = ecxt_callback;
     942     1905812 : }
     943             : 
     944             : /*
     945             :  * Deregister a shutdown callback in an ExprContext.
     946             :  *
     947             :  * Any list entries matching the function and arg will be removed.
     948             :  * This can be used if it's no longer necessary to call the callback.
     949             :  */
     950             : void
     951     1841924 : UnregisterExprContextCallback(ExprContext *econtext,
     952             :                               ExprContextCallbackFunction function,
     953             :                               Datum arg)
     954             : {
     955             :     ExprContext_CB **prev_callback;
     956             :     ExprContext_CB *ecxt_callback;
     957             : 
     958     1841924 :     prev_callback = &econtext->ecxt_callbacks;
     959             : 
     960     3797832 :     while ((ecxt_callback = *prev_callback) != NULL)
     961             :     {
     962     1955908 :         if (ecxt_callback->function == function && ecxt_callback->arg == arg)
     963             :         {
     964     1841924 :             *prev_callback = ecxt_callback->next;
     965     1841924 :             pfree(ecxt_callback);
     966             :         }
     967             :         else
     968      113984 :             prev_callback = &ecxt_callback->next;
     969             :     }
     970     1841924 : }
     971             : 
     972             : /*
     973             :  * Call all the shutdown callbacks registered in an ExprContext.
     974             :  *
     975             :  * The callback list is emptied (important in case this is only a rescan
     976             :  * reset, and not deletion of the ExprContext).
     977             :  *
     978             :  * If isCommit is false, just clean the callback list but don't call 'em.
     979             :  * (See comment for FreeExprContext.)
     980             :  */
     981             : static void
     982    14813716 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
     983             : {
     984             :     ExprContext_CB *ecxt_callback;
     985             :     MemoryContext oldcontext;
     986             : 
     987             :     /* Fast path in normal case where there's nothing to do. */
     988    14813716 :     if (econtext->ecxt_callbacks == NULL)
     989    14750678 :         return;
     990             : 
     991             :     /*
     992             :      * Call the callbacks in econtext's per-tuple context.  This ensures that
     993             :      * any memory they might leak will get cleaned up.
     994             :      */
     995       63038 :     oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
     996             : 
     997             :     /*
     998             :      * Call each callback function in reverse registration order.
     999             :      */
    1000      126328 :     while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
    1001             :     {
    1002       63290 :         econtext->ecxt_callbacks = ecxt_callback->next;
    1003       63290 :         if (isCommit)
    1004       63290 :             ecxt_callback->function(ecxt_callback->arg);
    1005       63290 :         pfree(ecxt_callback);
    1006             :     }
    1007             : 
    1008       63038 :     MemoryContextSwitchTo(oldcontext);
    1009             : }
    1010             : 
    1011             : /*
    1012             :  *      GetAttributeByName
    1013             :  *      GetAttributeByNum
    1014             :  *
    1015             :  *      These functions return the value of the requested attribute
    1016             :  *      out of the given tuple Datum.
    1017             :  *      C functions which take a tuple as an argument are expected
    1018             :  *      to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
    1019             :  *      Note: these are actually rather slow because they do a typcache
    1020             :  *      lookup on each call.
    1021             :  */
    1022             : Datum
    1023          24 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
    1024             : {
    1025             :     AttrNumber  attrno;
    1026             :     Datum       result;
    1027             :     Oid         tupType;
    1028             :     int32       tupTypmod;
    1029             :     TupleDesc   tupDesc;
    1030             :     HeapTupleData tmptup;
    1031             :     int         i;
    1032             : 
    1033          24 :     if (attname == NULL)
    1034           0 :         elog(ERROR, "invalid attribute name");
    1035             : 
    1036          24 :     if (isNull == NULL)
    1037           0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1038             : 
    1039          24 :     if (tuple == NULL)
    1040             :     {
    1041             :         /* Kinda bogus but compatible with old behavior... */
    1042           0 :         *isNull = true;
    1043           0 :         return (Datum) 0;
    1044             :     }
    1045             : 
    1046          24 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1047          24 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1048          24 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1049             : 
    1050          24 :     attrno = InvalidAttrNumber;
    1051          96 :     for (i = 0; i < tupDesc->natts; i++)
    1052             :     {
    1053          96 :         Form_pg_attribute att = TupleDescAttr(tupDesc, i);
    1054             : 
    1055          96 :         if (namestrcmp(&(att->attname), attname) == 0)
    1056             :         {
    1057          24 :             attrno = att->attnum;
    1058          24 :             break;
    1059             :         }
    1060             :     }
    1061             : 
    1062          24 :     if (attrno == InvalidAttrNumber)
    1063           0 :         elog(ERROR, "attribute \"%s\" does not exist", attname);
    1064             : 
    1065             :     /*
    1066             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1067             :      * the fields in the struct just in case user tries to inspect system
    1068             :      * columns.
    1069             :      */
    1070          24 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1071          24 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1072          24 :     tmptup.t_tableOid = InvalidOid;
    1073          24 :     tmptup.t_data = tuple;
    1074             : 
    1075          24 :     result = heap_getattr(&tmptup,
    1076             :                           attrno,
    1077             :                           tupDesc,
    1078             :                           isNull);
    1079             : 
    1080          24 :     ReleaseTupleDesc(tupDesc);
    1081             : 
    1082          24 :     return result;
    1083             : }
    1084             : 
    1085             : Datum
    1086           0 : GetAttributeByNum(HeapTupleHeader tuple,
    1087             :                   AttrNumber attrno,
    1088             :                   bool *isNull)
    1089             : {
    1090             :     Datum       result;
    1091             :     Oid         tupType;
    1092             :     int32       tupTypmod;
    1093             :     TupleDesc   tupDesc;
    1094             :     HeapTupleData tmptup;
    1095             : 
    1096           0 :     if (!AttributeNumberIsValid(attrno))
    1097           0 :         elog(ERROR, "invalid attribute number %d", attrno);
    1098             : 
    1099           0 :     if (isNull == NULL)
    1100           0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1101             : 
    1102           0 :     if (tuple == NULL)
    1103             :     {
    1104             :         /* Kinda bogus but compatible with old behavior... */
    1105           0 :         *isNull = true;
    1106           0 :         return (Datum) 0;
    1107             :     }
    1108             : 
    1109           0 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1110           0 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1111           0 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1112             : 
    1113             :     /*
    1114             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1115             :      * the fields in the struct just in case user tries to inspect system
    1116             :      * columns.
    1117             :      */
    1118           0 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1119           0 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1120           0 :     tmptup.t_tableOid = InvalidOid;
    1121           0 :     tmptup.t_data = tuple;
    1122             : 
    1123           0 :     result = heap_getattr(&tmptup,
    1124             :                           attrno,
    1125             :                           tupDesc,
    1126             :                           isNull);
    1127             : 
    1128           0 :     ReleaseTupleDesc(tupDesc);
    1129             : 
    1130           0 :     return result;
    1131             : }
    1132             : 
    1133             : /*
    1134             :  * Number of items in a tlist (including any resjunk items!)
    1135             :  */
    1136             : int
    1137     1243000 : ExecTargetListLength(List *targetlist)
    1138             : {
    1139             :     /* This used to be more complex, but fjoins are dead */
    1140     1243000 :     return list_length(targetlist);
    1141             : }
    1142             : 
    1143             : /*
    1144             :  * Number of items in a tlist, not including any resjunk items
    1145             :  */
    1146             : int
    1147      112642 : ExecCleanTargetListLength(List *targetlist)
    1148             : {
    1149      112642 :     int         len = 0;
    1150             :     ListCell   *tl;
    1151             : 
    1152      285588 :     foreach(tl, targetlist)
    1153             :     {
    1154      172946 :         TargetEntry *curTle = lfirst_node(TargetEntry, tl);
    1155             : 
    1156      172946 :         if (!curTle->resjunk)
    1157      155610 :             len++;
    1158             :     }
    1159      112642 :     return len;
    1160             : }
    1161             : 
    1162             : /*
    1163             :  * Return a relInfo's tuple slot for a trigger's OLD tuples.
    1164             :  */
    1165             : TupleTableSlot *
    1166       14756 : ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
    1167             : {
    1168       14756 :     if (relInfo->ri_TrigOldSlot == NULL)
    1169             :     {
    1170        5872 :         Relation    rel = relInfo->ri_RelationDesc;
    1171        5872 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1172             : 
    1173        5872 :         relInfo->ri_TrigOldSlot =
    1174        5872 :             ExecInitExtraTupleSlot(estate,
    1175             :                                    RelationGetDescr(rel),
    1176             :                                    table_slot_callbacks(rel));
    1177             : 
    1178        5872 :         MemoryContextSwitchTo(oldcontext);
    1179             :     }
    1180             : 
    1181       14756 :     return relInfo->ri_TrigOldSlot;
    1182             : }
    1183             : 
    1184             : /*
    1185             :  * Return a relInfo's tuple slot for a trigger's NEW tuples.
    1186             :  */
    1187             : TupleTableSlot *
    1188        1708 : ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
    1189             : {
    1190        1708 :     if (relInfo->ri_TrigNewSlot == NULL)
    1191             :     {
    1192        1026 :         Relation    rel = relInfo->ri_RelationDesc;
    1193        1026 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1194             : 
    1195        1026 :         relInfo->ri_TrigNewSlot =
    1196        1026 :             ExecInitExtraTupleSlot(estate,
    1197             :                                    RelationGetDescr(rel),
    1198             :                                    table_slot_callbacks(rel));
    1199             : 
    1200        1026 :         MemoryContextSwitchTo(oldcontext);
    1201             :     }
    1202             : 
    1203        1708 :     return relInfo->ri_TrigNewSlot;
    1204             : }
    1205             : 
    1206             : /*
    1207             :  * Return a relInfo's tuple slot for processing returning tuples.
    1208             :  */
    1209             : TupleTableSlot *
    1210         846 : ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
    1211             : {
    1212         846 :     if (relInfo->ri_ReturningSlot == NULL)
    1213             :     {
    1214         354 :         Relation    rel = relInfo->ri_RelationDesc;
    1215         354 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1216             : 
    1217         354 :         relInfo->ri_ReturningSlot =
    1218         354 :             ExecInitExtraTupleSlot(estate,
    1219             :                                    RelationGetDescr(rel),
    1220             :                                    table_slot_callbacks(rel));
    1221             : 
    1222         354 :         MemoryContextSwitchTo(oldcontext);
    1223             :     }
    1224             : 
    1225         846 :     return relInfo->ri_ReturningSlot;
    1226             : }
    1227             : 
    1228             : /*
    1229             :  * Return the map needed to convert given child result relation's tuples to
    1230             :  * the rowtype of the query's main target ("root") relation.  Note that a
    1231             :  * NULL result is valid and means that no conversion is needed.
    1232             :  */
    1233             : TupleConversionMap *
    1234       44244 : ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
    1235             : {
    1236             :     /* If we didn't already do so, compute the map for this child. */
    1237       44244 :     if (!resultRelInfo->ri_ChildToRootMapValid)
    1238             :     {
    1239         804 :         ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
    1240             : 
    1241         804 :         if (rootRelInfo)
    1242         574 :             resultRelInfo->ri_ChildToRootMap =
    1243         574 :                 convert_tuples_by_name(RelationGetDescr(resultRelInfo->ri_RelationDesc),
    1244         574 :                                        RelationGetDescr(rootRelInfo->ri_RelationDesc));
    1245             :         else                    /* this isn't a child result rel */
    1246         230 :             resultRelInfo->ri_ChildToRootMap = NULL;
    1247             : 
    1248         804 :         resultRelInfo->ri_ChildToRootMapValid = true;
    1249             :     }
    1250             : 
    1251       44244 :     return resultRelInfo->ri_ChildToRootMap;
    1252             : }
    1253             : 
    1254             : /* Return a bitmap representing columns being inserted */
    1255             : Bitmapset *
    1256         732 : ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
    1257             : {
    1258             :     /*
    1259             :      * The columns are stored in the range table entry.  If this ResultRelInfo
    1260             :      * represents a partition routing target, and doesn't have an entry of its
    1261             :      * own in the range table, fetch the parent's RTE and map the columns to
    1262             :      * the order they are in the partition.
    1263             :      */
    1264         732 :     if (relinfo->ri_RangeTableIndex != 0)
    1265             :     {
    1266         732 :         RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
    1267             : 
    1268         732 :         return rte->insertedCols;
    1269             :     }
    1270           0 :     else if (relinfo->ri_RootResultRelInfo)
    1271             :     {
    1272           0 :         ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
    1273           0 :         RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
    1274             : 
    1275           0 :         if (relinfo->ri_RootToPartitionMap != NULL)
    1276           0 :             return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap,
    1277             :                                          rte->insertedCols);
    1278             :         else
    1279           0 :             return rte->insertedCols;
    1280             :     }
    1281             :     else
    1282             :     {
    1283             :         /*
    1284             :          * The relation isn't in the range table and it isn't a partition
    1285             :          * routing target.  This ResultRelInfo must've been created only for
    1286             :          * firing triggers and the relation is not being inserted into.  (See
    1287             :          * ExecGetTriggerResultRel.)
    1288             :          */
    1289           0 :         return NULL;
    1290             :     }
    1291             : }
    1292             : 
    1293             : /* Return a bitmap representing columns being updated */
    1294             : Bitmapset *
    1295      370784 : ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1296             : {
    1297             :     /* see ExecGetInsertedCols() */
    1298      370784 :     if (relinfo->ri_RangeTableIndex != 0)
    1299             :     {
    1300      370680 :         RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
    1301             : 
    1302      370680 :         return rte->updatedCols;
    1303             :     }
    1304         104 :     else if (relinfo->ri_RootResultRelInfo)
    1305             :     {
    1306         104 :         ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
    1307         104 :         RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
    1308             : 
    1309         104 :         if (relinfo->ri_RootToPartitionMap != NULL)
    1310          38 :             return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap,
    1311             :                                          rte->updatedCols);
    1312             :         else
    1313          66 :             return rte->updatedCols;
    1314             :     }
    1315             :     else
    1316           0 :         return NULL;
    1317             : }
    1318             : 
    1319             : /* Return a bitmap representing generated columns being updated */
    1320             : Bitmapset *
    1321      370084 : ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1322             : {
    1323             :     /* see ExecGetInsertedCols() */
    1324      370084 :     if (relinfo->ri_RangeTableIndex != 0)
    1325             :     {
    1326      369980 :         RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
    1327             : 
    1328      369980 :         return rte->extraUpdatedCols;
    1329             :     }
    1330         104 :     else if (relinfo->ri_RootResultRelInfo)
    1331             :     {
    1332         104 :         ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
    1333         104 :         RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
    1334             : 
    1335         104 :         if (relinfo->ri_RootToPartitionMap != NULL)
    1336          38 :             return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap,
    1337             :                                          rte->extraUpdatedCols);
    1338             :         else
    1339          66 :             return rte->extraUpdatedCols;
    1340             :     }
    1341             :     else
    1342           0 :         return NULL;
    1343             : }
    1344             : 
    1345             : /* Return columns being updated, including generated columns */
    1346             : Bitmapset *
    1347       11274 : ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1348             : {
    1349       11274 :     return bms_union(ExecGetUpdatedCols(relinfo, estate),
    1350       11274 :                      ExecGetExtraUpdatedCols(relinfo, estate));
    1351             : }

Generated by: LCOV version 1.14