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

Generated by: LCOV version 2.0-1