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

Generated by: LCOV version 2.0-1