LCOV - code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 366 408 89.7 %
Date: 2023-06-06 09:15:10 Functions: 40 43 93.0 %
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     1225740 : 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     1225740 :     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     1225740 :     oldcontext = MemoryContextSwitchTo(qcontext);
     111             : 
     112     1225740 :     estate = makeNode(EState);
     113             : 
     114             :     /*
     115             :      * Initialize all fields of the Executor State structure
     116             :      */
     117     1225740 :     estate->es_direction = ForwardScanDirection;
     118     1225740 :     estate->es_snapshot = InvalidSnapshot;   /* caller must initialize this */
     119     1225740 :     estate->es_crosscheck_snapshot = InvalidSnapshot;    /* no crosscheck */
     120     1225740 :     estate->es_range_table = NIL;
     121     1225740 :     estate->es_range_table_size = 0;
     122     1225740 :     estate->es_relations = NULL;
     123     1225740 :     estate->es_rowmarks = NULL;
     124     1225740 :     estate->es_rteperminfos = NIL;
     125     1225740 :     estate->es_plannedstmt = NULL;
     126             : 
     127     1225740 :     estate->es_junkFilter = NULL;
     128             : 
     129     1225740 :     estate->es_output_cid = (CommandId) 0;
     130             : 
     131     1225740 :     estate->es_result_relations = NULL;
     132     1225740 :     estate->es_opened_result_relations = NIL;
     133     1225740 :     estate->es_tuple_routing_result_relations = NIL;
     134     1225740 :     estate->es_trig_target_relations = NIL;
     135             : 
     136     1225740 :     estate->es_insert_pending_result_relations = NIL;
     137     1225740 :     estate->es_insert_pending_modifytables = NIL;
     138             : 
     139     1225740 :     estate->es_param_list_info = NULL;
     140     1225740 :     estate->es_param_exec_vals = NULL;
     141             : 
     142     1225740 :     estate->es_queryEnv = NULL;
     143             : 
     144     1225740 :     estate->es_query_cxt = qcontext;
     145             : 
     146     1225740 :     estate->es_tupleTable = NIL;
     147             : 
     148     1225740 :     estate->es_processed = 0;
     149     1225740 :     estate->es_total_processed = 0;
     150             : 
     151     1225740 :     estate->es_top_eflags = 0;
     152     1225740 :     estate->es_instrument = 0;
     153     1225740 :     estate->es_finished = false;
     154             : 
     155     1225740 :     estate->es_exprcontexts = NIL;
     156             : 
     157     1225740 :     estate->es_subplanstates = NIL;
     158             : 
     159     1225740 :     estate->es_auxmodifytables = NIL;
     160             : 
     161     1225740 :     estate->es_per_tuple_exprcontext = NULL;
     162             : 
     163     1225740 :     estate->es_sourceText = NULL;
     164             : 
     165     1225740 :     estate->es_use_parallel_mode = false;
     166             : 
     167     1225740 :     estate->es_jit_flags = 0;
     168     1225740 :     estate->es_jit = NULL;
     169             : 
     170             :     /*
     171             :      * Return the executor state structure
     172             :      */
     173     1225740 :     MemoryContextSwitchTo(oldcontext);
     174             : 
     175     1225740 :     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     1195934 : 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     2979982 :     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     1784048 :         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     1195934 :     if (estate->es_jit)
     215             :     {
     216        1650 :         jit_release_context(estate->es_jit);
     217        1650 :         estate->es_jit = NULL;
     218             :     }
     219             : 
     220             :     /* release partition directory, if allocated */
     221     1195934 :     if (estate->es_partition_directory)
     222             :     {
     223        6234 :         DestroyPartitionDirectory(estate->es_partition_directory);
     224        6234 :         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     1195934 :     MemoryContextDelete(estate->es_query_cxt);
     232     1195934 : }
     233             : 
     234             : /*
     235             :  * Internal implementation for CreateExprContext() and CreateWorkExprContext()
     236             :  * that allows control over the AllocSet parameters.
     237             :  */
     238             : static ExprContext *
     239     1909362 : 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     1909362 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     247             : 
     248     1909362 :     econtext = makeNode(ExprContext);
     249             : 
     250             :     /* Initialize fields of ExprContext */
     251     1909362 :     econtext->ecxt_scantuple = NULL;
     252     1909362 :     econtext->ecxt_innertuple = NULL;
     253     1909362 :     econtext->ecxt_outertuple = NULL;
     254             : 
     255     1909362 :     econtext->ecxt_per_query_memory = estate->es_query_cxt;
     256             : 
     257             :     /*
     258             :      * Create working memory for expression evaluation in this context.
     259             :      */
     260     1909362 :     econtext->ecxt_per_tuple_memory =
     261     1909362 :         AllocSetContextCreate(estate->es_query_cxt,
     262             :                               "ExprContext",
     263             :                               minContextSize,
     264             :                               initBlockSize,
     265             :                               maxBlockSize);
     266             : 
     267     1909362 :     econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
     268     1909362 :     econtext->ecxt_param_list_info = estate->es_param_list_info;
     269             : 
     270     1909362 :     econtext->ecxt_aggvalues = NULL;
     271     1909362 :     econtext->ecxt_aggnulls = NULL;
     272             : 
     273     1909362 :     econtext->caseValue_datum = (Datum) 0;
     274     1909362 :     econtext->caseValue_isNull = true;
     275             : 
     276     1909362 :     econtext->domainValue_datum = (Datum) 0;
     277     1909362 :     econtext->domainValue_isNull = true;
     278             : 
     279     1909362 :     econtext->ecxt_estate = estate;
     280             : 
     281     1909362 :     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     1909362 :     estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
     289             : 
     290     1909362 :     MemoryContextSwitchTo(oldcontext);
     291             : 
     292     1909362 :     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     1901600 : CreateExprContext(EState *estate)
     310             : {
     311     1901600 :     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        7762 : CreateWorkExprContext(EState *estate)
     325             : {
     326        7762 :     Size        minContextSize = ALLOCSET_DEFAULT_MINSIZE;
     327        7762 :     Size        initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
     328        7762 :     Size        maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
     329             : 
     330             :     /* choose the maxBlockSize to be no larger than 1/16 of work_mem */
     331       47112 :     while (16 * maxBlockSize > work_mem * 1024L)
     332       39350 :         maxBlockSize >>= 1;
     333             : 
     334        7762 :     if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
     335          78 :         maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
     336             : 
     337        7762 :     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       11268 : CreateStandaloneExprContext(void)
     361             : {
     362             :     ExprContext *econtext;
     363             : 
     364             :     /* Create the ExprContext node within the caller's memory context */
     365       11268 :     econtext = makeNode(ExprContext);
     366             : 
     367             :     /* Initialize fields of ExprContext */
     368       11268 :     econtext->ecxt_scantuple = NULL;
     369       11268 :     econtext->ecxt_innertuple = NULL;
     370       11268 :     econtext->ecxt_outertuple = NULL;
     371             : 
     372       11268 :     econtext->ecxt_per_query_memory = CurrentMemoryContext;
     373             : 
     374             :     /*
     375             :      * Create working memory for expression evaluation in this context.
     376             :      */
     377       11268 :     econtext->ecxt_per_tuple_memory =
     378       11268 :         AllocSetContextCreate(CurrentMemoryContext,
     379             :                               "ExprContext",
     380             :                               ALLOCSET_DEFAULT_SIZES);
     381             : 
     382       11268 :     econtext->ecxt_param_exec_vals = NULL;
     383       11268 :     econtext->ecxt_param_list_info = NULL;
     384             : 
     385       11268 :     econtext->ecxt_aggvalues = NULL;
     386       11268 :     econtext->ecxt_aggnulls = NULL;
     387             : 
     388       11268 :     econtext->caseValue_datum = (Datum) 0;
     389       11268 :     econtext->caseValue_isNull = true;
     390             : 
     391       11268 :     econtext->domainValue_datum = (Datum) 0;
     392       11268 :     econtext->domainValue_isNull = true;
     393             : 
     394       11268 :     econtext->ecxt_estate = NULL;
     395             : 
     396       11268 :     econtext->ecxt_callbacks = NULL;
     397             : 
     398       11268 :     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     1875432 : FreeExprContext(ExprContext *econtext, bool isCommit)
     420             : {
     421             :     EState     *estate;
     422             : 
     423             :     /* Call any registered callbacks */
     424     1875432 :     ShutdownExprContext(econtext, isCommit);
     425             :     /* And clean up the memory used */
     426     1875432 :     MemoryContextDelete(econtext->ecxt_per_tuple_memory);
     427             :     /* Unlink self from owning EState, if any */
     428     1875432 :     estate = econtext->ecxt_estate;
     429     1875432 :     if (estate)
     430     1875432 :         estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
     431             :                                                   econtext);
     432             :     /* And delete the ExprContext node */
     433     1875432 :     pfree(econtext);
     434     1875432 : }
     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     3995708 : ReScanExprContext(ExprContext *econtext)
     447             : {
     448             :     /* Call any registered callbacks */
     449     3995708 :     ShutdownExprContext(econtext, true);
     450             :     /* And clean up the memory used */
     451     3995708 :     MemoryContextReset(econtext->ecxt_per_tuple_memory);
     452     3995708 : }
     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      715454 : MakePerTupleExprContext(EState *estate)
     462             : {
     463      715454 :     if (estate->es_per_tuple_exprcontext == NULL)
     464      715454 :         estate->es_per_tuple_exprcontext = CreateExprContext(estate);
     465             : 
     466      715454 :     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     1079238 : ExecAssignExprContext(EState *estate, PlanState *planstate)
     489             : {
     490     1079238 :     planstate->ps_ExprContext = CreateExprContext(estate);
     491     1079238 : }
     492             : 
     493             : /* ----------------
     494             :  *      ExecGetResultType
     495             :  * ----------------
     496             :  */
     497             : TupleDesc
     498     1288626 : ExecGetResultType(PlanState *planstate)
     499             : {
     500     1288626 :     return planstate->ps_ResultTupleDesc;
     501             : }
     502             : 
     503             : /*
     504             :  * ExecGetResultSlotOps - information about node's type of result slot
     505             :  */
     506             : const TupleTableSlotOps *
     507      484958 : ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
     508             : {
     509      484958 :     if (planstate->resultopsset && planstate->resultops)
     510             :     {
     511      483554 :         if (isfixed)
     512      439898 :             *isfixed = planstate->resultopsfixed;
     513      483554 :         return planstate->resultops;
     514             :     }
     515             : 
     516        1404 :     if (isfixed)
     517             :     {
     518        1368 :         if (planstate->resultopsset)
     519        1368 :             *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        1404 :     if (!planstate->ps_ResultTupleSlot)
     527        1404 :         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      646860 : ExecAssignProjectionInfo(PlanState *planstate,
     544             :                          TupleDesc inputDesc)
     545             : {
     546      646790 :     planstate->ps_ProjInfo =
     547      646860 :         ExecBuildProjectionInfo(planstate->plan->targetlist,
     548             :                                 planstate->ps_ExprContext,
     549             :                                 planstate->ps_ResultTupleSlot,
     550             :                                 planstate,
     551             :                                 inputDesc);
     552      646790 : }
     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      421882 : ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
     564             :                                     int varno)
     565             : {
     566      421882 :     if (tlist_matches_tupdesc(planstate,
     567      421882 :                               planstate->plan->targetlist,
     568             :                               varno,
     569             :                               inputDesc))
     570             :     {
     571      218790 :         planstate->ps_ProjInfo = NULL;
     572      218790 :         planstate->resultopsset = planstate->scanopsset;
     573      218790 :         planstate->resultopsfixed = planstate->scanopsfixed;
     574      218790 :         planstate->resultops = planstate->scanops;
     575             :     }
     576             :     else
     577             :     {
     578      203092 :         if (!planstate->ps_ResultTupleSlot)
     579             :         {
     580      203092 :             ExecInitResultSlot(planstate, &TTSOpsVirtual);
     581      203092 :             planstate->resultops = &TTSOpsVirtual;
     582      203092 :             planstate->resultopsfixed = true;
     583      203092 :             planstate->resultopsset = true;
     584             :         }
     585      203092 :         ExecAssignProjectionInfo(planstate, inputDesc);
     586             :     }
     587      421882 : }
     588             : 
     589             : static bool
     590      421882 : tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
     591             : {
     592      421882 :     int         numattrs = tupdesc->natts;
     593             :     int         attrno;
     594      421882 :     ListCell   *tlist_item = list_head(tlist);
     595             : 
     596             :     /* Check the tlist attributes */
     597     2890724 :     for (attrno = 1; attrno <= numattrs; attrno++)
     598             :     {
     599     2660018 :         Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
     600             :         Var        *var;
     601             : 
     602     2660018 :         if (tlist_item == NULL)
     603       31652 :             return false;       /* tlist too short */
     604     2628366 :         var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
     605     2628366 :         if (!var || !IsA(var, Var))
     606       59154 :             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     2569212 :         if (var->varattno != attrno)
     611      100082 :             return false;       /* out of order */
     612     2469130 :         if (att_tup->attisdropped)
     613           0 :             return false;       /* table contains dropped columns */
     614     2469130 :         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     2468848 :         if (var->vartype != att_tup->atttypid ||
     628     2468842 :             (var->vartypmod != att_tup->atttypmod &&
     629           6 :              var->vartypmod != -1))
     630           6 :             return false;       /* type mismatch */
     631             : 
     632     2468842 :         tlist_item = lnext(tlist, tlist_item);
     633             :     }
     634             : 
     635      230706 :     if (tlist_item)
     636       11916 :         return false;           /* tlist too long */
     637             : 
     638      218790 :     return true;
     639             : }
     640             : 
     641             : /* ----------------
     642             :  *      ExecFreeExprContext
     643             :  *
     644             :  * A plan node's ExprContext should be freed explicitly during executor
     645             :  * shutdown because there may be shutdown callbacks to call.  (Other resources
     646             :  * made by the above routines, such as projection info, don't need to be freed
     647             :  * explicitly because they're just memory in the per-query memory context.)
     648             :  *
     649             :  * However ... there is no particular need to do it during ExecEndNode,
     650             :  * because FreeExecutorState will free any remaining ExprContexts within
     651             :  * the EState.  Letting FreeExecutorState do it allows the ExprContexts to
     652             :  * be freed in reverse order of creation, rather than order of creation as
     653             :  * will happen if we delete them here, which saves O(N^2) work in the list
     654             :  * cleanup inside FreeExprContext.
     655             :  * ----------------
     656             :  */
     657             : void
     658      896290 : ExecFreeExprContext(PlanState *planstate)
     659             : {
     660             :     /*
     661             :      * Per above discussion, don't actually delete the ExprContext. We do
     662             :      * unlink it from the plan node, though.
     663             :      */
     664      896290 :     planstate->ps_ExprContext = NULL;
     665      896290 : }
     666             : 
     667             : 
     668             : /* ----------------------------------------------------------------
     669             :  *                Scan node support
     670             :  * ----------------------------------------------------------------
     671             :  */
     672             : 
     673             : /* ----------------
     674             :  *      ExecAssignScanType
     675             :  * ----------------
     676             :  */
     677             : void
     678         648 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
     679             : {
     680         648 :     TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
     681             : 
     682         648 :     ExecSetSlotDescriptor(slot, tupDesc);
     683         648 : }
     684             : 
     685             : /* ----------------
     686             :  *      ExecCreateScanSlotFromOuterPlan
     687             :  * ----------------
     688             :  */
     689             : void
     690      100202 : ExecCreateScanSlotFromOuterPlan(EState *estate,
     691             :                                 ScanState *scanstate,
     692             :                                 const TupleTableSlotOps *tts_ops)
     693             : {
     694             :     PlanState  *outerPlan;
     695             :     TupleDesc   tupDesc;
     696             : 
     697      100202 :     outerPlan = outerPlanState(scanstate);
     698      100202 :     tupDesc = ExecGetResultType(outerPlan);
     699             : 
     700      100202 :     ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
     701      100202 : }
     702             : 
     703             : /* ----------------------------------------------------------------
     704             :  *      ExecRelationIsTargetRelation
     705             :  *
     706             :  *      Detect whether a relation (identified by rangetable index)
     707             :  *      is one of the target relations of the query.
     708             :  *
     709             :  * Note: This is currently no longer used in core.  We keep it around
     710             :  * because FDWs may wish to use it to determine if their foreign table
     711             :  * is a target relation.
     712             :  * ----------------------------------------------------------------
     713             :  */
     714             : bool
     715           0 : ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
     716             : {
     717           0 :     return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
     718             : }
     719             : 
     720             : /* ----------------------------------------------------------------
     721             :  *      ExecOpenScanRelation
     722             :  *
     723             :  *      Open the heap relation to be scanned by a base-level scan plan node.
     724             :  *      This should be called during the node's ExecInit routine.
     725             :  * ----------------------------------------------------------------
     726             :  */
     727             : Relation
     728      340882 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
     729             : {
     730             :     Relation    rel;
     731             : 
     732             :     /* Open the relation. */
     733      340882 :     rel = ExecGetRangeTableRelation(estate, scanrelid);
     734             : 
     735             :     /*
     736             :      * Complain if we're attempting a scan of an unscannable relation, except
     737             :      * when the query won't actually be run.  This is a slightly klugy place
     738             :      * to do this, perhaps, but there is no better place.
     739             :      */
     740      340882 :     if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
     741      313844 :         !RelationIsScannable(rel))
     742          12 :         ereport(ERROR,
     743             :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
     744             :                  errmsg("materialized view \"%s\" has not been populated",
     745             :                         RelationGetRelationName(rel)),
     746             :                  errhint("Use the REFRESH MATERIALIZED VIEW command.")));
     747             : 
     748      340870 :     return rel;
     749             : }
     750             : 
     751             : /*
     752             :  * ExecInitRangeTable
     753             :  *      Set up executor's range-table-related data
     754             :  *
     755             :  * In addition to the range table proper, initialize arrays that are
     756             :  * indexed by rangetable index.
     757             :  */
     758             : void
     759      834202 : ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos)
     760             : {
     761             :     /* Remember the range table List as-is */
     762      834202 :     estate->es_range_table = rangeTable;
     763             : 
     764             :     /* ... and the RTEPermissionInfo List too */
     765      834202 :     estate->es_rteperminfos = permInfos;
     766             : 
     767             :     /* Set size of associated arrays */
     768      834202 :     estate->es_range_table_size = list_length(rangeTable);
     769             : 
     770             :     /*
     771             :      * Allocate an array to store an open Relation corresponding to each
     772             :      * rangetable entry, and initialize entries to NULL.  Relations are opened
     773             :      * and stored here as needed.
     774             :      */
     775      834202 :     estate->es_relations = (Relation *)
     776      834202 :         palloc0(estate->es_range_table_size * sizeof(Relation));
     777             : 
     778             :     /*
     779             :      * es_result_relations and es_rowmarks are also parallel to
     780             :      * es_range_table, but are allocated only if needed.
     781             :      */
     782      834202 :     estate->es_result_relations = NULL;
     783      834202 :     estate->es_rowmarks = NULL;
     784      834202 : }
     785             : 
     786             : /*
     787             :  * ExecGetRangeTableRelation
     788             :  *      Open the Relation for a range table entry, if not already done
     789             :  *
     790             :  * The Relations will be closed again in ExecEndPlan().
     791             :  */
     792             : Relation
     793      496616 : ExecGetRangeTableRelation(EState *estate, Index rti)
     794             : {
     795             :     Relation    rel;
     796             : 
     797             :     Assert(rti > 0 && rti <= estate->es_range_table_size);
     798             : 
     799      496616 :     rel = estate->es_relations[rti - 1];
     800      496616 :     if (rel == NULL)
     801             :     {
     802             :         /* First time through, so open the relation */
     803      452014 :         RangeTblEntry *rte = exec_rt_fetch(rti, estate);
     804             : 
     805             :         Assert(rte->rtekind == RTE_RELATION);
     806             : 
     807      452014 :         if (!IsParallelWorker())
     808             :         {
     809             :             /*
     810             :              * In a normal query, we should already have the appropriate lock,
     811             :              * but verify that through an Assert.  Since there's already an
     812             :              * Assert inside table_open that insists on holding some lock, it
     813             :              * seems sufficient to check this only when rellockmode is higher
     814             :              * than the minimum.
     815             :              */
     816      447450 :             rel = table_open(rte->relid, NoLock);
     817             :             Assert(rte->rellockmode == AccessShareLock ||
     818             :                    CheckRelationLockedByMe(rel, rte->rellockmode, false));
     819             :         }
     820             :         else
     821             :         {
     822             :             /*
     823             :              * If we are a parallel worker, we need to obtain our own local
     824             :              * lock on the relation.  This ensures sane behavior in case the
     825             :              * parent process exits before we do.
     826             :              */
     827        4564 :             rel = table_open(rte->relid, rte->rellockmode);
     828             :         }
     829             : 
     830      452014 :         estate->es_relations[rti - 1] = rel;
     831             :     }
     832             : 
     833      496616 :     return rel;
     834             : }
     835             : 
     836             : /*
     837             :  * ExecInitResultRelation
     838             :  *      Open relation given by the passed-in RT index and fill its
     839             :  *      ResultRelInfo node
     840             :  *
     841             :  * Here, we also save the ResultRelInfo in estate->es_result_relations array
     842             :  * such that it can be accessed later using the RT index.
     843             :  */
     844             : void
     845      145854 : ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
     846             :                        Index rti)
     847             : {
     848             :     Relation    resultRelationDesc;
     849             : 
     850      145854 :     resultRelationDesc = ExecGetRangeTableRelation(estate, rti);
     851      145854 :     InitResultRelInfo(resultRelInfo,
     852             :                       resultRelationDesc,
     853             :                       rti,
     854             :                       NULL,
     855             :                       estate->es_instrument);
     856             : 
     857      145854 :     if (estate->es_result_relations == NULL)
     858      136306 :         estate->es_result_relations = (ResultRelInfo **)
     859      136306 :             palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
     860      145854 :     estate->es_result_relations[rti - 1] = resultRelInfo;
     861             : 
     862             :     /*
     863             :      * Saving in the list allows to avoid needlessly traversing the whole
     864             :      * array when only a few of its entries are possibly non-NULL.
     865             :      */
     866      145854 :     estate->es_opened_result_relations =
     867      145854 :         lappend(estate->es_opened_result_relations, resultRelInfo);
     868      145854 : }
     869             : 
     870             : /*
     871             :  * UpdateChangedParamSet
     872             :  *      Add changed parameters to a plan node's chgParam set
     873             :  */
     874             : void
     875      952154 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
     876             : {
     877             :     Bitmapset  *parmset;
     878             : 
     879             :     /*
     880             :      * The plan node only depends on params listed in its allParam set. Don't
     881             :      * include anything else into its chgParam set.
     882             :      */
     883      952154 :     parmset = bms_intersect(node->plan->allParam, newchg);
     884      952154 :     node->chgParam = bms_join(node->chgParam, parmset);
     885      952154 : }
     886             : 
     887             : /*
     888             :  * executor_errposition
     889             :  *      Report an execution-time cursor position, if possible.
     890             :  *
     891             :  * This is expected to be used within an ereport() call.  The return value
     892             :  * is a dummy (always 0, in fact).
     893             :  *
     894             :  * The locations stored in parsetrees are byte offsets into the source string.
     895             :  * We have to convert them to 1-based character indexes for reporting to
     896             :  * clients.  (We do things this way to avoid unnecessary overhead in the
     897             :  * normal non-error case: computing character indexes would be much more
     898             :  * expensive than storing token offsets.)
     899             :  */
     900             : int
     901           0 : executor_errposition(EState *estate, int location)
     902             : {
     903             :     int         pos;
     904             : 
     905             :     /* No-op if location was not provided */
     906           0 :     if (location < 0)
     907           0 :         return 0;
     908             :     /* Can't do anything if source text is not available */
     909           0 :     if (estate == NULL || estate->es_sourceText == NULL)
     910           0 :         return 0;
     911             :     /* Convert offset to character number */
     912           0 :     pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
     913             :     /* And pass it to the ereport mechanism */
     914           0 :     return errposition(pos);
     915             : }
     916             : 
     917             : /*
     918             :  * Register a shutdown callback in an ExprContext.
     919             :  *
     920             :  * Shutdown callbacks will be called (in reverse order of registration)
     921             :  * when the ExprContext is deleted or rescanned.  This provides a hook
     922             :  * for functions called in the context to do any cleanup needed --- it's
     923             :  * particularly useful for functions returning sets.  Note that the
     924             :  * callback will *not* be called in the event that execution is aborted
     925             :  * by an error.
     926             :  */
     927             : void
     928      243998 : RegisterExprContextCallback(ExprContext *econtext,
     929             :                             ExprContextCallbackFunction function,
     930             :                             Datum arg)
     931             : {
     932             :     ExprContext_CB *ecxt_callback;
     933             : 
     934             :     /* Save the info in appropriate memory context */
     935             :     ecxt_callback = (ExprContext_CB *)
     936      243998 :         MemoryContextAlloc(econtext->ecxt_per_query_memory,
     937             :                            sizeof(ExprContext_CB));
     938             : 
     939      243998 :     ecxt_callback->function = function;
     940      243998 :     ecxt_callback->arg = arg;
     941             : 
     942             :     /* link to front of list for appropriate execution order */
     943      243998 :     ecxt_callback->next = econtext->ecxt_callbacks;
     944      243998 :     econtext->ecxt_callbacks = ecxt_callback;
     945      243998 : }
     946             : 
     947             : /*
     948             :  * Deregister a shutdown callback in an ExprContext.
     949             :  *
     950             :  * Any list entries matching the function and arg will be removed.
     951             :  * This can be used if it's no longer necessary to call the callback.
     952             :  */
     953             : void
     954      160242 : UnregisterExprContextCallback(ExprContext *econtext,
     955             :                               ExprContextCallbackFunction function,
     956             :                               Datum arg)
     957             : {
     958             :     ExprContext_CB **prev_callback;
     959             :     ExprContext_CB *ecxt_callback;
     960             : 
     961      160242 :     prev_callback = &econtext->ecxt_callbacks;
     962             : 
     963      483026 :     while ((ecxt_callback = *prev_callback) != NULL)
     964             :     {
     965      322784 :         if (ecxt_callback->function == function && ecxt_callback->arg == arg)
     966             :         {
     967      160242 :             *prev_callback = ecxt_callback->next;
     968      160242 :             pfree(ecxt_callback);
     969             :         }
     970             :         else
     971      162542 :             prev_callback = &ecxt_callback->next;
     972             :     }
     973      160242 : }
     974             : 
     975             : /*
     976             :  * Call all the shutdown callbacks registered in an ExprContext.
     977             :  *
     978             :  * The callback list is emptied (important in case this is only a rescan
     979             :  * reset, and not deletion of the ExprContext).
     980             :  *
     981             :  * If isCommit is false, just clean the callback list but don't call 'em.
     982             :  * (See comment for FreeExprContext.)
     983             :  */
     984             : static void
     985     5871140 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
     986             : {
     987             :     ExprContext_CB *ecxt_callback;
     988             :     MemoryContext oldcontext;
     989             : 
     990             :     /* Fast path in normal case where there's nothing to do. */
     991     5871140 :     if (econtext->ecxt_callbacks == NULL)
     992     5788590 :         return;
     993             : 
     994             :     /*
     995             :      * Call the callbacks in econtext's per-tuple context.  This ensures that
     996             :      * any memory they might leak will get cleaned up.
     997             :      */
     998       82550 :     oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
     999             : 
    1000             :     /*
    1001             :      * Call each callback function in reverse registration order.
    1002             :      */
    1003      165494 :     while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
    1004             :     {
    1005       82944 :         econtext->ecxt_callbacks = ecxt_callback->next;
    1006       82944 :         if (isCommit)
    1007       82944 :             ecxt_callback->function(ecxt_callback->arg);
    1008       82944 :         pfree(ecxt_callback);
    1009             :     }
    1010             : 
    1011       82550 :     MemoryContextSwitchTo(oldcontext);
    1012             : }
    1013             : 
    1014             : /*
    1015             :  *      GetAttributeByName
    1016             :  *      GetAttributeByNum
    1017             :  *
    1018             :  *      These functions return the value of the requested attribute
    1019             :  *      out of the given tuple Datum.
    1020             :  *      C functions which take a tuple as an argument are expected
    1021             :  *      to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
    1022             :  *      Note: these are actually rather slow because they do a typcache
    1023             :  *      lookup on each call.
    1024             :  */
    1025             : Datum
    1026          36 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
    1027             : {
    1028             :     AttrNumber  attrno;
    1029             :     Datum       result;
    1030             :     Oid         tupType;
    1031             :     int32       tupTypmod;
    1032             :     TupleDesc   tupDesc;
    1033             :     HeapTupleData tmptup;
    1034             :     int         i;
    1035             : 
    1036          36 :     if (attname == NULL)
    1037           0 :         elog(ERROR, "invalid attribute name");
    1038             : 
    1039          36 :     if (isNull == NULL)
    1040           0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1041             : 
    1042          36 :     if (tuple == NULL)
    1043             :     {
    1044             :         /* Kinda bogus but compatible with old behavior... */
    1045           0 :         *isNull = true;
    1046           0 :         return (Datum) 0;
    1047             :     }
    1048             : 
    1049          36 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1050          36 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1051          36 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1052             : 
    1053          36 :     attrno = InvalidAttrNumber;
    1054         144 :     for (i = 0; i < tupDesc->natts; i++)
    1055             :     {
    1056         144 :         Form_pg_attribute att = TupleDescAttr(tupDesc, i);
    1057             : 
    1058         144 :         if (namestrcmp(&(att->attname), attname) == 0)
    1059             :         {
    1060          36 :             attrno = att->attnum;
    1061          36 :             break;
    1062             :         }
    1063             :     }
    1064             : 
    1065          36 :     if (attrno == InvalidAttrNumber)
    1066           0 :         elog(ERROR, "attribute \"%s\" does not exist", attname);
    1067             : 
    1068             :     /*
    1069             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1070             :      * the fields in the struct just in case user tries to inspect system
    1071             :      * columns.
    1072             :      */
    1073          36 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1074          36 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1075          36 :     tmptup.t_tableOid = InvalidOid;
    1076          36 :     tmptup.t_data = tuple;
    1077             : 
    1078          36 :     result = heap_getattr(&tmptup,
    1079             :                           attrno,
    1080             :                           tupDesc,
    1081             :                           isNull);
    1082             : 
    1083          36 :     ReleaseTupleDesc(tupDesc);
    1084             : 
    1085          36 :     return result;
    1086             : }
    1087             : 
    1088             : Datum
    1089           0 : GetAttributeByNum(HeapTupleHeader tuple,
    1090             :                   AttrNumber attrno,
    1091             :                   bool *isNull)
    1092             : {
    1093             :     Datum       result;
    1094             :     Oid         tupType;
    1095             :     int32       tupTypmod;
    1096             :     TupleDesc   tupDesc;
    1097             :     HeapTupleData tmptup;
    1098             : 
    1099           0 :     if (!AttributeNumberIsValid(attrno))
    1100           0 :         elog(ERROR, "invalid attribute number %d", attrno);
    1101             : 
    1102           0 :     if (isNull == NULL)
    1103           0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1104             : 
    1105           0 :     if (tuple == NULL)
    1106             :     {
    1107             :         /* Kinda bogus but compatible with old behavior... */
    1108           0 :         *isNull = true;
    1109           0 :         return (Datum) 0;
    1110             :     }
    1111             : 
    1112           0 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1113           0 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1114           0 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1115             : 
    1116             :     /*
    1117             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1118             :      * the fields in the struct just in case user tries to inspect system
    1119             :      * columns.
    1120             :      */
    1121           0 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1122           0 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1123           0 :     tmptup.t_tableOid = InvalidOid;
    1124           0 :     tmptup.t_data = tuple;
    1125             : 
    1126           0 :     result = heap_getattr(&tmptup,
    1127             :                           attrno,
    1128             :                           tupDesc,
    1129             :                           isNull);
    1130             : 
    1131           0 :     ReleaseTupleDesc(tupDesc);
    1132             : 
    1133           0 :     return result;
    1134             : }
    1135             : 
    1136             : /*
    1137             :  * Number of items in a tlist (including any resjunk items!)
    1138             :  */
    1139             : int
    1140     1147064 : ExecTargetListLength(List *targetlist)
    1141             : {
    1142             :     /* This used to be more complex, but fjoins are dead */
    1143     1147064 :     return list_length(targetlist);
    1144             : }
    1145             : 
    1146             : /*
    1147             :  * Number of items in a tlist, not including any resjunk items
    1148             :  */
    1149             : int
    1150      162532 : ExecCleanTargetListLength(List *targetlist)
    1151             : {
    1152      162532 :     int         len = 0;
    1153             :     ListCell   *tl;
    1154             : 
    1155      577094 :     foreach(tl, targetlist)
    1156             :     {
    1157      414562 :         TargetEntry *curTle = lfirst_node(TargetEntry, tl);
    1158             : 
    1159      414562 :         if (!curTle->resjunk)
    1160      388376 :             len++;
    1161             :     }
    1162      162532 :     return len;
    1163             : }
    1164             : 
    1165             : /*
    1166             :  * Return a relInfo's tuple slot for a trigger's OLD tuples.
    1167             :  */
    1168             : TupleTableSlot *
    1169       22292 : ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
    1170             : {
    1171       22292 :     if (relInfo->ri_TrigOldSlot == NULL)
    1172             :     {
    1173        8952 :         Relation    rel = relInfo->ri_RelationDesc;
    1174        8952 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1175             : 
    1176        8952 :         relInfo->ri_TrigOldSlot =
    1177        8952 :             ExecInitExtraTupleSlot(estate,
    1178             :                                    RelationGetDescr(rel),
    1179             :                                    table_slot_callbacks(rel));
    1180             : 
    1181        8952 :         MemoryContextSwitchTo(oldcontext);
    1182             :     }
    1183             : 
    1184       22292 :     return relInfo->ri_TrigOldSlot;
    1185             : }
    1186             : 
    1187             : /*
    1188             :  * Return a relInfo's tuple slot for a trigger's NEW tuples.
    1189             :  */
    1190             : TupleTableSlot *
    1191        3186 : ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
    1192             : {
    1193        3186 :     if (relInfo->ri_TrigNewSlot == NULL)
    1194             :     {
    1195        1912 :         Relation    rel = relInfo->ri_RelationDesc;
    1196        1912 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1197             : 
    1198        1912 :         relInfo->ri_TrigNewSlot =
    1199        1912 :             ExecInitExtraTupleSlot(estate,
    1200             :                                    RelationGetDescr(rel),
    1201             :                                    table_slot_callbacks(rel));
    1202             : 
    1203        1912 :         MemoryContextSwitchTo(oldcontext);
    1204             :     }
    1205             : 
    1206        3186 :     return relInfo->ri_TrigNewSlot;
    1207             : }
    1208             : 
    1209             : /*
    1210             :  * Return a relInfo's tuple slot for processing returning tuples.
    1211             :  */
    1212             : TupleTableSlot *
    1213        1090 : ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
    1214             : {
    1215        1090 :     if (relInfo->ri_ReturningSlot == NULL)
    1216             :     {
    1217         482 :         Relation    rel = relInfo->ri_RelationDesc;
    1218         482 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1219             : 
    1220         482 :         relInfo->ri_ReturningSlot =
    1221         482 :             ExecInitExtraTupleSlot(estate,
    1222             :                                    RelationGetDescr(rel),
    1223             :                                    table_slot_callbacks(rel));
    1224             : 
    1225         482 :         MemoryContextSwitchTo(oldcontext);
    1226             :     }
    1227             : 
    1228        1090 :     return relInfo->ri_ReturningSlot;
    1229             : }
    1230             : 
    1231             : /*
    1232             :  * Return the map needed to convert given child result relation's tuples to
    1233             :  * the rowtype of the query's main target ("root") relation.  Note that a
    1234             :  * NULL result is valid and means that no conversion is needed.
    1235             :  */
    1236             : TupleConversionMap *
    1237       67544 : ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
    1238             : {
    1239             :     /* If we didn't already do so, compute the map for this child. */
    1240       67544 :     if (!resultRelInfo->ri_ChildToRootMapValid)
    1241             :     {
    1242        1504 :         ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
    1243             : 
    1244        1504 :         if (rootRelInfo)
    1245        1132 :             resultRelInfo->ri_ChildToRootMap =
    1246        1132 :                 convert_tuples_by_name(RelationGetDescr(resultRelInfo->ri_RelationDesc),
    1247        1132 :                                        RelationGetDescr(rootRelInfo->ri_RelationDesc));
    1248             :         else                    /* this isn't a child result rel */
    1249         372 :             resultRelInfo->ri_ChildToRootMap = NULL;
    1250             : 
    1251        1504 :         resultRelInfo->ri_ChildToRootMapValid = true;
    1252             :     }
    1253             : 
    1254       67544 :     return resultRelInfo->ri_ChildToRootMap;
    1255             : }
    1256             : 
    1257             : /*
    1258             :  * Returns the map needed to convert given root result relation's tuples to
    1259             :  * the rowtype of the given child relation.  Note that a NULL result is valid
    1260             :  * and means that no conversion is needed.
    1261             :  */
    1262             : TupleConversionMap *
    1263      945792 : ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
    1264             : {
    1265             :     /* Mustn't get called for a non-child result relation. */
    1266             :     Assert(resultRelInfo->ri_RootResultRelInfo);
    1267             : 
    1268             :     /* If we didn't already do so, compute the map for this child. */
    1269      945792 :     if (!resultRelInfo->ri_RootToChildMapValid)
    1270             :     {
    1271        8820 :         ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
    1272        8820 :         TupleDesc   indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
    1273        8820 :         TupleDesc   outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
    1274        8820 :         Relation    childrel = resultRelInfo->ri_RelationDesc;
    1275             :         AttrMap    *attrMap;
    1276             :         MemoryContext oldcontext;
    1277             : 
    1278             :         /*
    1279             :          * When this child table is not a partition (!relispartition), it may
    1280             :          * have columns that are not present in the root table, which we ask
    1281             :          * to ignore by passing true for missing_ok.
    1282             :          */
    1283        8820 :         oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1284        8820 :         attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
    1285        8820 :                                                !childrel->rd_rel->relispartition);
    1286        8820 :         if (attrMap)
    1287        1378 :             resultRelInfo->ri_RootToChildMap =
    1288        1378 :                 convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
    1289        8820 :         MemoryContextSwitchTo(oldcontext);
    1290        8820 :         resultRelInfo->ri_RootToChildMapValid = true;
    1291             :     }
    1292             : 
    1293      945792 :     return resultRelInfo->ri_RootToChildMap;
    1294             : }
    1295             : 
    1296             : /* Return a bitmap representing columns being inserted */
    1297             : Bitmapset *
    1298        1090 : ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
    1299             : {
    1300        1090 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
    1301             : 
    1302        1090 :     if (perminfo == NULL)
    1303           0 :         return NULL;
    1304             : 
    1305             :     /* Map the columns to child's attribute numbers if needed. */
    1306        1090 :     if (relinfo->ri_RootResultRelInfo)
    1307             :     {
    1308         118 :         TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
    1309             : 
    1310         118 :         if (map)
    1311           0 :             return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
    1312             :     }
    1313             : 
    1314        1090 :     return perminfo->insertedCols;
    1315             : }
    1316             : 
    1317             : /* Return a bitmap representing columns being updated */
    1318             : Bitmapset *
    1319       60068 : ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1320             : {
    1321       60068 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
    1322             : 
    1323       60068 :     if (perminfo == NULL)
    1324           0 :         return NULL;
    1325             : 
    1326             :     /* Map the columns to child's attribute numbers if needed. */
    1327       60068 :     if (relinfo->ri_RootResultRelInfo)
    1328             :     {
    1329        1674 :         TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
    1330             : 
    1331        1674 :         if (map)
    1332         486 :             return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
    1333             :     }
    1334             : 
    1335       59582 :     return perminfo->updatedCols;
    1336             : }
    1337             : 
    1338             : /* Return a bitmap representing generated columns being updated */
    1339             : Bitmapset *
    1340       58776 : ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1341             : {
    1342             :     /* Compute the info if we didn't already */
    1343       58776 :     if (relinfo->ri_GeneratedExprsU == NULL)
    1344       58656 :         ExecInitStoredGenerated(relinfo, estate, CMD_UPDATE);
    1345       58776 :     return relinfo->ri_extraUpdatedCols;
    1346             : }
    1347             : 
    1348             : /* Return columns being updated, including generated columns */
    1349             : Bitmapset *
    1350       14146 : ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1351             : {
    1352       14146 :     return bms_union(ExecGetUpdatedCols(relinfo, estate),
    1353       14146 :                      ExecGetExtraUpdatedCols(relinfo, estate));
    1354             : }
    1355             : 
    1356             : /*
    1357             :  * GetResultRTEPermissionInfo
    1358             :  *      Looks up RTEPermissionInfo for ExecGet*Cols() routines
    1359             :  */
    1360             : static RTEPermissionInfo *
    1361       61498 : GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
    1362             : {
    1363             :     Index       rti;
    1364             :     RangeTblEntry *rte;
    1365       61498 :     RTEPermissionInfo *perminfo = NULL;
    1366             : 
    1367       61498 :     if (relinfo->ri_RootResultRelInfo)
    1368             :     {
    1369             :         /*
    1370             :          * For inheritance child result relations (a partition routing target
    1371             :          * of an INSERT or a child UPDATE target), this returns the root
    1372             :          * parent's RTE to fetch the RTEPermissionInfo because that's the only
    1373             :          * one that has one assigned.
    1374             :          */
    1375        1888 :         rti = relinfo->ri_RootResultRelInfo->ri_RangeTableIndex;
    1376             :     }
    1377       59610 :     else if (relinfo->ri_RangeTableIndex != 0)
    1378             :     {
    1379             :         /*
    1380             :          * Non-child result relation should have their own RTEPermissionInfo.
    1381             :          */
    1382       59610 :         rti = relinfo->ri_RangeTableIndex;
    1383             :     }
    1384             :     else
    1385             :     {
    1386             :         /*
    1387             :          * The relation isn't in the range table and it isn't a partition
    1388             :          * routing target.  This ResultRelInfo must've been created only for
    1389             :          * firing triggers and the relation is not being inserted into.  (See
    1390             :          * ExecGetTriggerResultRel.)
    1391             :          */
    1392           0 :         rti = 0;
    1393             :     }
    1394             : 
    1395       61498 :     if (rti > 0)
    1396             :     {
    1397       61498 :         rte = exec_rt_fetch(rti, estate);
    1398       61498 :         perminfo = getRTEPermissionInfo(estate->es_rteperminfos, rte);
    1399             :     }
    1400             : 
    1401       61498 :     return perminfo;
    1402             : }
    1403             : 
    1404             : /*
    1405             :  * ExecGetResultRelCheckAsUser
    1406             :  *      Returns the user to modify passed-in result relation as
    1407             :  *
    1408             :  * The user is chosen by looking up the relation's or, if a child table, its
    1409             :  * root parent's RTEPermissionInfo.
    1410             :  */
    1411             : Oid
    1412         340 : ExecGetResultRelCheckAsUser(ResultRelInfo *relInfo, EState *estate)
    1413             : {
    1414         340 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relInfo, estate);
    1415             : 
    1416             :     /* XXX - maybe ok to return GetUserId() in this case? */
    1417         340 :     if (perminfo == NULL)
    1418           0 :         elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
    1419             :              RelationGetRelid(relInfo->ri_RelationDesc));
    1420             : 
    1421         340 :     return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
    1422             : }

Generated by: LCOV version 1.14