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

Generated by: LCOV version 1.14