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

Generated by: LCOV version 1.14