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

Generated by: LCOV version 1.14