LCOV - code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 90.4 % 439 397
Test Date: 2026-03-17 19:16:11 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 "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      1145571 : 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      1145571 :     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      1145571 :     oldcontext = MemoryContextSwitchTo(qcontext);
     108              : 
     109      1145571 :     estate = makeNode(EState);
     110              : 
     111              :     /*
     112              :      * Initialize all fields of the Executor State structure
     113              :      */
     114      1145571 :     estate->es_direction = ForwardScanDirection;
     115      1145571 :     estate->es_snapshot = InvalidSnapshot;   /* caller must initialize this */
     116      1145571 :     estate->es_crosscheck_snapshot = InvalidSnapshot;    /* no crosscheck */
     117      1145571 :     estate->es_range_table = NIL;
     118      1145571 :     estate->es_range_table_size = 0;
     119      1145571 :     estate->es_relations = NULL;
     120      1145571 :     estate->es_rowmarks = NULL;
     121      1145571 :     estate->es_rteperminfos = NIL;
     122      1145571 :     estate->es_plannedstmt = NULL;
     123      1145571 :     estate->es_part_prune_infos = NIL;
     124      1145571 :     estate->es_part_prune_states = NIL;
     125      1145571 :     estate->es_part_prune_results = NIL;
     126      1145571 :     estate->es_unpruned_relids = NULL;
     127              : 
     128      1145571 :     estate->es_junkFilter = NULL;
     129              : 
     130      1145571 :     estate->es_output_cid = (CommandId) 0;
     131              : 
     132      1145571 :     estate->es_result_relations = NULL;
     133      1145571 :     estate->es_opened_result_relations = NIL;
     134      1145571 :     estate->es_tuple_routing_result_relations = NIL;
     135      1145571 :     estate->es_trig_target_relations = NIL;
     136              : 
     137      1145571 :     estate->es_insert_pending_result_relations = NIL;
     138      1145571 :     estate->es_insert_pending_modifytables = NIL;
     139              : 
     140      1145571 :     estate->es_param_list_info = NULL;
     141      1145571 :     estate->es_param_exec_vals = NULL;
     142              : 
     143      1145571 :     estate->es_queryEnv = NULL;
     144              : 
     145      1145571 :     estate->es_query_cxt = qcontext;
     146              : 
     147      1145571 :     estate->es_tupleTable = NIL;
     148              : 
     149      1145571 :     estate->es_processed = 0;
     150      1145571 :     estate->es_total_processed = 0;
     151              : 
     152      1145571 :     estate->es_top_eflags = 0;
     153      1145571 :     estate->es_instrument = 0;
     154      1145571 :     estate->es_finished = false;
     155              : 
     156      1145571 :     estate->es_exprcontexts = NIL;
     157              : 
     158      1145571 :     estate->es_subplanstates = NIL;
     159              : 
     160      1145571 :     estate->es_auxmodifytables = NIL;
     161              : 
     162      1145571 :     estate->es_per_tuple_exprcontext = NULL;
     163              : 
     164      1145571 :     estate->es_sourceText = NULL;
     165              : 
     166      1145571 :     estate->es_use_parallel_mode = false;
     167      1145571 :     estate->es_parallel_workers_to_launch = 0;
     168      1145571 :     estate->es_parallel_workers_launched = 0;
     169              : 
     170      1145571 :     estate->es_jit_flags = 0;
     171      1145571 :     estate->es_jit = NULL;
     172              : 
     173              :     /*
     174              :      * Return the executor state structure
     175              :      */
     176      1145571 :     MemoryContextSwitchTo(oldcontext);
     177              : 
     178      1145571 :     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      1122046 : 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      2880573 :     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      1758527 :         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      1122046 :     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      1122046 :     if (estate->es_partition_directory)
     225              :     {
     226         4507 :         DestroyPartitionDirectory(estate->es_partition_directory);
     227         4507 :         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      1122046 :     MemoryContextDelete(estate->es_query_cxt);
     235      1122046 : }
     236              : 
     237              : /*
     238              :  * Internal implementation for CreateExprContext() and CreateWorkExprContext()
     239              :  * that allows control over the AllocSet parameters.
     240              :  */
     241              : static ExprContext *
     242      1849000 : 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      1849000 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     250              : 
     251      1849000 :     econtext = makeNode(ExprContext);
     252              : 
     253              :     /* Initialize fields of ExprContext */
     254      1849000 :     econtext->ecxt_scantuple = NULL;
     255      1849000 :     econtext->ecxt_innertuple = NULL;
     256      1849000 :     econtext->ecxt_outertuple = NULL;
     257              : 
     258      1849000 :     econtext->ecxt_per_query_memory = estate->es_query_cxt;
     259              : 
     260              :     /*
     261              :      * Create working memory for expression evaluation in this context.
     262              :      */
     263      1849000 :     econtext->ecxt_per_tuple_memory =
     264      1849000 :         AllocSetContextCreate(estate->es_query_cxt,
     265              :                               "ExprContext",
     266              :                               minContextSize,
     267              :                               initBlockSize,
     268              :                               maxBlockSize);
     269              : 
     270      1849000 :     econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
     271      1849000 :     econtext->ecxt_param_list_info = estate->es_param_list_info;
     272              : 
     273      1849000 :     econtext->ecxt_aggvalues = NULL;
     274      1849000 :     econtext->ecxt_aggnulls = NULL;
     275              : 
     276      1849000 :     econtext->caseValue_datum = (Datum) 0;
     277      1849000 :     econtext->caseValue_isNull = true;
     278              : 
     279      1849000 :     econtext->domainValue_datum = (Datum) 0;
     280      1849000 :     econtext->domainValue_isNull = true;
     281              : 
     282      1849000 :     econtext->ecxt_estate = estate;
     283              : 
     284      1849000 :     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      1849000 :     estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
     292              : 
     293      1849000 :     MemoryContextSwitchTo(oldcontext);
     294              : 
     295      1849000 :     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      1844435 : CreateExprContext(EState *estate)
     313              : {
     314      1844435 :     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         4565 : CreateWorkExprContext(EState *estate)
     328              : {
     329              :     Size        maxBlockSize;
     330              : 
     331         4565 :     maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
     332              : 
     333              :     /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
     334         4565 :     maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
     335              : 
     336              :     /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
     337         4565 :     maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
     338              : 
     339         4565 :     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         6383 : CreateStandaloneExprContext(void)
     363              : {
     364              :     ExprContext *econtext;
     365              : 
     366              :     /* Create the ExprContext node within the caller's memory context */
     367         6383 :     econtext = makeNode(ExprContext);
     368              : 
     369              :     /* Initialize fields of ExprContext */
     370         6383 :     econtext->ecxt_scantuple = NULL;
     371         6383 :     econtext->ecxt_innertuple = NULL;
     372         6383 :     econtext->ecxt_outertuple = NULL;
     373              : 
     374         6383 :     econtext->ecxt_per_query_memory = CurrentMemoryContext;
     375              : 
     376              :     /*
     377              :      * Create working memory for expression evaluation in this context.
     378              :      */
     379         6383 :     econtext->ecxt_per_tuple_memory =
     380         6383 :         AllocSetContextCreate(CurrentMemoryContext,
     381              :                               "ExprContext",
     382              :                               ALLOCSET_DEFAULT_SIZES);
     383              : 
     384         6383 :     econtext->ecxt_param_exec_vals = NULL;
     385         6383 :     econtext->ecxt_param_list_info = NULL;
     386              : 
     387         6383 :     econtext->ecxt_aggvalues = NULL;
     388         6383 :     econtext->ecxt_aggnulls = NULL;
     389              : 
     390         6383 :     econtext->caseValue_datum = (Datum) 0;
     391         6383 :     econtext->caseValue_isNull = true;
     392              : 
     393         6383 :     econtext->domainValue_datum = (Datum) 0;
     394         6383 :     econtext->domainValue_isNull = true;
     395              : 
     396         6383 :     econtext->ecxt_estate = NULL;
     397              : 
     398         6383 :     econtext->ecxt_callbacks = NULL;
     399              : 
     400         6383 :     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      1821126 : FreeExprContext(ExprContext *econtext, bool isCommit)
     422              : {
     423              :     EState     *estate;
     424              : 
     425              :     /* Call any registered callbacks */
     426      1821126 :     ShutdownExprContext(econtext, isCommit);
     427              :     /* And clean up the memory used */
     428      1821126 :     MemoryContextDelete(econtext->ecxt_per_tuple_memory);
     429              :     /* Unlink self from owning EState, if any */
     430      1821126 :     estate = econtext->ecxt_estate;
     431      1821126 :     if (estate)
     432      1821126 :         estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
     433              :                                                   econtext);
     434              :     /* And delete the ExprContext node */
     435      1821126 :     pfree(econtext);
     436      1821126 : }
     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      2965645 : ReScanExprContext(ExprContext *econtext)
     449              : {
     450              :     /* Call any registered callbacks */
     451      2965645 :     ShutdownExprContext(econtext, true);
     452              :     /* And clean up the memory used */
     453      2965645 :     MemoryContextReset(econtext->ecxt_per_tuple_memory);
     454      2965645 : }
     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       401208 : MakePerTupleExprContext(EState *estate)
     464              : {
     465       401208 :     if (estate->es_per_tuple_exprcontext == NULL)
     466       401208 :         estate->es_per_tuple_exprcontext = CreateExprContext(estate);
     467              : 
     468       401208 :     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      1366538 : ExecAssignExprContext(EState *estate, PlanState *planstate)
     491              : {
     492      1366538 :     planstate->ps_ExprContext = CreateExprContext(estate);
     493      1366538 : }
     494              : 
     495              : /* ----------------
     496              :  *      ExecGetResultType
     497              :  * ----------------
     498              :  */
     499              : TupleDesc
     500      1477007 : ExecGetResultType(PlanState *planstate)
     501              : {
     502      1477007 :     return planstate->ps_ResultTupleDesc;
     503              : }
     504              : 
     505              : /*
     506              :  * ExecGetResultSlotOps - information about node's type of result slot
     507              :  */
     508              : const TupleTableSlotOps *
     509       895643 : ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
     510              : {
     511       895643 :     if (planstate->resultopsset && planstate->resultops)
     512              :     {
     513       894513 :         if (isfixed)
     514       847826 :             *isfixed = planstate->resultopsfixed;
     515       894513 :         return planstate->resultops;
     516              :     }
     517              : 
     518         1130 :     if (isfixed)
     519              :     {
     520         1108 :         if (planstate->resultopsset)
     521         1108 :             *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         1130 :     if (!planstate->ps_ResultTupleSlot)
     529         1130 :         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        13393 : ExecGetCommonSlotOps(PlanState **planstates, int nplans)
     542              : {
     543              :     const TupleTableSlotOps *result;
     544              :     bool        isfixed;
     545              : 
     546        13393 :     if (nplans <= 0)
     547           68 :         return NULL;
     548        13325 :     result = ExecGetResultSlotOps(planstates[0], &isfixed);
     549        13325 :     if (!isfixed)
     550           60 :         return NULL;
     551        38534 :     for (int i = 1; i < nplans; i++)
     552              :     {
     553              :         const TupleTableSlotOps *thisops;
     554              : 
     555        25910 :         thisops = ExecGetResultSlotOps(planstates[i], &isfixed);
     556        25910 :         if (!isfixed)
     557           27 :             return NULL;
     558        25883 :         if (result != thisops)
     559          614 :             return NULL;
     560              :     }
     561        12624 :     return result;
     562              : }
     563              : 
     564              : /*
     565              :  * ExecGetCommonChildSlotOps - as above, for the PlanState's standard children
     566              :  */
     567              : const TupleTableSlotOps *
     568          581 : ExecGetCommonChildSlotOps(PlanState *ps)
     569              : {
     570              :     PlanState  *planstates[2];
     571              : 
     572          581 :     planstates[0] = outerPlanState(ps);
     573          581 :     planstates[1] = innerPlanState(ps);
     574          581 :     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       884893 : ExecAssignProjectionInfo(PlanState *planstate,
     589              :                          TupleDesc inputDesc)
     590              : {
     591       884853 :     planstate->ps_ProjInfo =
     592       884893 :         ExecBuildProjectionInfo(planstate->plan->targetlist,
     593              :                                 planstate->ps_ExprContext,
     594              :                                 planstate->ps_ResultTupleSlot,
     595              :                                 planstate,
     596              :                                 inputDesc);
     597       884853 : }
     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       770738 : ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
     609              :                                     int varno)
     610              : {
     611       770738 :     if (tlist_matches_tupdesc(planstate,
     612       770738 :                               planstate->plan->targetlist,
     613              :                               varno,
     614              :                               inputDesc))
     615              :     {
     616       193319 :         planstate->ps_ProjInfo = NULL;
     617       193319 :         planstate->resultopsset = planstate->scanopsset;
     618       193319 :         planstate->resultopsfixed = planstate->scanopsfixed;
     619       193319 :         planstate->resultops = planstate->scanops;
     620              :     }
     621              :     else
     622              :     {
     623       577419 :         if (!planstate->ps_ResultTupleSlot)
     624              :         {
     625       577419 :             ExecInitResultSlot(planstate, &TTSOpsVirtual);
     626       577419 :             planstate->resultops = &TTSOpsVirtual;
     627       577419 :             planstate->resultopsfixed = true;
     628       577419 :             planstate->resultopsset = true;
     629              :         }
     630       577419 :         ExecAssignProjectionInfo(planstate, inputDesc);
     631              :     }
     632       770738 : }
     633              : 
     634              : static bool
     635       770738 : tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
     636              : {
     637       770738 :     int         numattrs = tupdesc->natts;
     638              :     int         attrno;
     639       770738 :     ListCell   *tlist_item = list_head(tlist);
     640              : 
     641              :     /* Check the tlist attributes */
     642      2895133 :     for (attrno = 1; attrno <= numattrs; attrno++)
     643              :     {
     644      2694053 :         Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
     645              :         Var        *var;
     646              : 
     647      2694053 :         if (tlist_item == NULL)
     648        22725 :             return false;       /* tlist too short */
     649      2671328 :         var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
     650      2671328 :         if (!var || !IsA(var, Var))
     651       445375 :             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      2225953 :         if (var->varattno != attrno)
     656       101340 :             return false;       /* out of order */
     657      2124613 :         if (att_tup->attisdropped)
     658            0 :             return false;       /* table contains dropped columns */
     659      2124613 :         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      2124399 :         if (var->vartype != att_tup->atttypid ||
     673      2124395 :             (var->vartypmod != att_tup->atttypmod &&
     674            4 :              var->vartypmod != -1))
     675            4 :             return false;       /* type mismatch */
     676              : 
     677      2124395 :         tlist_item = lnext(tlist, tlist_item);
     678              :     }
     679              : 
     680       201080 :     if (tlist_item)
     681         7761 :         return false;           /* tlist too long */
     682              : 
     683       193319 :     return true;
     684              : }
     685              : 
     686              : 
     687              : /* ----------------------------------------------------------------
     688              :  *                Scan node support
     689              :  * ----------------------------------------------------------------
     690              :  */
     691              : 
     692              : /* ----------------
     693              :  *      ExecAssignScanType
     694              :  * ----------------
     695              :  */
     696              : void
     697          579 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
     698              : {
     699          579 :     TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
     700              : 
     701          579 :     ExecSetSlotDescriptor(slot, tupDesc);
     702          579 : }
     703              : 
     704              : /* ----------------
     705              :  *      ExecCreateScanSlotFromOuterPlan
     706              :  * ----------------
     707              :  */
     708              : void
     709        96373 : ExecCreateScanSlotFromOuterPlan(EState *estate,
     710              :                                 ScanState *scanstate,
     711              :                                 const TupleTableSlotOps *tts_ops)
     712              : {
     713              :     PlanState  *outerPlan;
     714              :     TupleDesc   tupDesc;
     715              : 
     716        96373 :     outerPlan = outerPlanState(scanstate);
     717        96373 :     tupDesc = ExecGetResultType(outerPlan);
     718              : 
     719        96373 :     ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops, 0);
     720        96373 : }
     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 list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
     737              : }
     738              : 
     739              : /* ----------------------------------------------------------------
     740              :  *      ExecOpenScanRelation
     741              :  *
     742              :  *      Open the heap relation to be scanned by a base-level scan plan node.
     743              :  *      This should be called during the node's ExecInit routine.
     744              :  * ----------------------------------------------------------------
     745              :  */
     746              : Relation
     747       701275 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
     748              : {
     749              :     Relation    rel;
     750              : 
     751              :     /* Open the relation. */
     752       701275 :     rel = ExecGetRangeTableRelation(estate, scanrelid, false);
     753              : 
     754              :     /*
     755              :      * Complain if we're attempting a scan of an unscannable relation, except
     756              :      * when the query won't actually be run.  This is a slightly klugy place
     757              :      * to do this, perhaps, but there is no better place.
     758              :      */
     759       701275 :     if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
     760       678586 :         !RelationIsScannable(rel))
     761            8 :         ereport(ERROR,
     762              :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
     763              :                  errmsg("materialized view \"%s\" has not been populated",
     764              :                         RelationGetRelationName(rel)),
     765              :                  errhint("Use the REFRESH MATERIALIZED VIEW command.")));
     766              : 
     767       701267 :     return rel;
     768              : }
     769              : 
     770              : /*
     771              :  * ExecInitRangeTable
     772              :  *      Set up executor's range-table-related data
     773              :  *
     774              :  * In addition to the range table proper, initialize arrays that are
     775              :  * indexed by rangetable index.
     776              :  */
     777              : void
     778       910059 : ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos,
     779              :                    Bitmapset *unpruned_relids)
     780              : {
     781              :     /* Remember the range table List as-is */
     782       910059 :     estate->es_range_table = rangeTable;
     783              : 
     784              :     /* ... and the RTEPermissionInfo List too */
     785       910059 :     estate->es_rteperminfos = permInfos;
     786              : 
     787              :     /* Set size of associated arrays */
     788       910059 :     estate->es_range_table_size = list_length(rangeTable);
     789              : 
     790              :     /*
     791              :      * Initialize the bitmapset of RT indexes (es_unpruned_relids)
     792              :      * representing relations that will be scanned during execution. This set
     793              :      * is initially populated by the caller and may be extended later by
     794              :      * ExecDoInitialPruning() to include RT indexes of unpruned leaf
     795              :      * partitions.
     796              :      */
     797       910059 :     estate->es_unpruned_relids = unpruned_relids;
     798              : 
     799              :     /*
     800              :      * Allocate an array to store an open Relation corresponding to each
     801              :      * rangetable entry, and initialize entries to NULL.  Relations are opened
     802              :      * and stored here as needed.
     803              :      */
     804       910059 :     estate->es_relations = (Relation *)
     805       910059 :         palloc0(estate->es_range_table_size * sizeof(Relation));
     806              : 
     807              :     /*
     808              :      * es_result_relations and es_rowmarks are also parallel to
     809              :      * es_range_table, but are allocated only if needed.
     810              :      */
     811       910059 :     estate->es_result_relations = NULL;
     812       910059 :     estate->es_rowmarks = NULL;
     813       910059 : }
     814              : 
     815              : /*
     816              :  * ExecGetRangeTableRelation
     817              :  *      Open the Relation for a range table entry, if not already done
     818              :  *
     819              :  * The Relations will be closed in ExecEndPlan().
     820              :  *
     821              :  * If isResultRel is true, the relation is being used as a result relation.
     822              :  * Such a relation might have been pruned, which is OK for result relations,
     823              :  * but not for scan relations; see the details in ExecInitModifyTable(). If
     824              :  * isResultRel is false, the caller must ensure that 'rti' refers to an
     825              :  * unpruned relation (i.e., it is a member of estate->es_unpruned_relids)
     826              :  * before calling this function. Attempting to open a pruned relation for
     827              :  * scanning will result in an error.
     828              :  */
     829              : Relation
     830      1190048 : ExecGetRangeTableRelation(EState *estate, Index rti, bool isResultRel)
     831              : {
     832              :     Relation    rel;
     833              : 
     834              :     Assert(rti > 0 && rti <= estate->es_range_table_size);
     835              : 
     836      1190048 :     if (!isResultRel && !bms_is_member(rti, estate->es_unpruned_relids))
     837            0 :         elog(ERROR, "trying to open a pruned relation");
     838              : 
     839      1190048 :     rel = estate->es_relations[rti - 1];
     840      1190048 :     if (rel == NULL)
     841              :     {
     842              :         /* First time through, so open the relation */
     843       761167 :         RangeTblEntry *rte = exec_rt_fetch(rti, estate);
     844              : 
     845              :         Assert(rte->rtekind == RTE_RELATION);
     846              : 
     847       761167 :         if (!IsParallelWorker())
     848              :         {
     849              :             /*
     850              :              * In a normal query, we should already have the appropriate lock,
     851              :              * but verify that through an Assert.  Since there's already an
     852              :              * Assert inside table_open that insists on holding some lock, it
     853              :              * seems sufficient to check this only when rellockmode is higher
     854              :              * than the minimum.
     855              :              */
     856       757430 :             rel = table_open(rte->relid, NoLock);
     857              :             Assert(rte->rellockmode == AccessShareLock ||
     858              :                    CheckRelationLockedByMe(rel, rte->rellockmode, false));
     859              :         }
     860              :         else
     861              :         {
     862              :             /*
     863              :              * If we are a parallel worker, we need to obtain our own local
     864              :              * lock on the relation.  This ensures sane behavior in case the
     865              :              * parent process exits before we do.
     866              :              */
     867         3737 :             rel = table_open(rte->relid, rte->rellockmode);
     868              :         }
     869              : 
     870       761167 :         estate->es_relations[rti - 1] = rel;
     871              :     }
     872              : 
     873      1190048 :     return rel;
     874              : }
     875              : 
     876              : /*
     877              :  * ExecInitResultRelation
     878              :  *      Open relation given by the passed-in RT index and fill its
     879              :  *      ResultRelInfo node
     880              :  *
     881              :  * Here, we also save the ResultRelInfo in estate->es_result_relations array
     882              :  * such that it can be accessed later using the RT index.
     883              :  */
     884              : void
     885        78086 : ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
     886              :                        Index rti)
     887              : {
     888              :     Relation    resultRelationDesc;
     889              : 
     890        78086 :     resultRelationDesc = ExecGetRangeTableRelation(estate, rti, true);
     891        78086 :     InitResultRelInfo(resultRelInfo,
     892              :                       resultRelationDesc,
     893              :                       rti,
     894              :                       NULL,
     895              :                       estate->es_instrument);
     896              : 
     897        78086 :     if (estate->es_result_relations == NULL)
     898        74527 :         estate->es_result_relations = (ResultRelInfo **)
     899        74527 :             palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
     900        78086 :     estate->es_result_relations[rti - 1] = resultRelInfo;
     901              : 
     902              :     /*
     903              :      * Saving in the list allows to avoid needlessly traversing the whole
     904              :      * array when only a few of its entries are possibly non-NULL.
     905              :      */
     906        78086 :     estate->es_opened_result_relations =
     907        78086 :         lappend(estate->es_opened_result_relations, resultRelInfo);
     908        78086 : }
     909              : 
     910              : /*
     911              :  * UpdateChangedParamSet
     912              :  *      Add changed parameters to a plan node's chgParam set
     913              :  */
     914              : void
     915       715701 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
     916              : {
     917              :     Bitmapset  *parmset;
     918              : 
     919              :     /*
     920              :      * The plan node only depends on params listed in its allParam set. Don't
     921              :      * include anything else into its chgParam set.
     922              :      */
     923       715701 :     parmset = bms_intersect(node->plan->allParam, newchg);
     924       715701 :     node->chgParam = bms_join(node->chgParam, parmset);
     925       715701 : }
     926              : 
     927              : /*
     928              :  * executor_errposition
     929              :  *      Report an execution-time cursor position, if possible.
     930              :  *
     931              :  * This is expected to be used within an ereport() call.  The return value
     932              :  * is a dummy (always 0, in fact).
     933              :  *
     934              :  * The locations stored in parsetrees are byte offsets into the source string.
     935              :  * We have to convert them to 1-based character indexes for reporting to
     936              :  * clients.  (We do things this way to avoid unnecessary overhead in the
     937              :  * normal non-error case: computing character indexes would be much more
     938              :  * expensive than storing token offsets.)
     939              :  */
     940              : int
     941            0 : executor_errposition(EState *estate, int location)
     942              : {
     943              :     int         pos;
     944              : 
     945              :     /* No-op if location was not provided */
     946            0 :     if (location < 0)
     947            0 :         return 0;
     948              :     /* Can't do anything if source text is not available */
     949            0 :     if (estate == NULL || estate->es_sourceText == NULL)
     950            0 :         return 0;
     951              :     /* Convert offset to character number */
     952            0 :     pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
     953              :     /* And pass it to the ereport mechanism */
     954            0 :     return errposition(pos);
     955              : }
     956              : 
     957              : /*
     958              :  * Register a shutdown callback in an ExprContext.
     959              :  *
     960              :  * Shutdown callbacks will be called (in reverse order of registration)
     961              :  * when the ExprContext is deleted or rescanned.  This provides a hook
     962              :  * for functions called in the context to do any cleanup needed --- it's
     963              :  * particularly useful for functions returning sets.  Note that the
     964              :  * callback will *not* be called in the event that execution is aborted
     965              :  * by an error.
     966              :  */
     967              : void
     968       175051 : RegisterExprContextCallback(ExprContext *econtext,
     969              :                             ExprContextCallbackFunction function,
     970              :                             Datum arg)
     971              : {
     972              :     ExprContext_CB *ecxt_callback;
     973              : 
     974              :     /* Save the info in appropriate memory context */
     975              :     ecxt_callback = (ExprContext_CB *)
     976       175051 :         MemoryContextAlloc(econtext->ecxt_per_query_memory,
     977              :                            sizeof(ExprContext_CB));
     978              : 
     979       175051 :     ecxt_callback->function = function;
     980       175051 :     ecxt_callback->arg = arg;
     981              : 
     982              :     /* link to front of list for appropriate execution order */
     983       175051 :     ecxt_callback->next = econtext->ecxt_callbacks;
     984       175051 :     econtext->ecxt_callbacks = ecxt_callback;
     985       175051 : }
     986              : 
     987              : /*
     988              :  * Deregister a shutdown callback in an ExprContext.
     989              :  *
     990              :  * Any list entries matching the function and arg will be removed.
     991              :  * This can be used if it's no longer necessary to call the callback.
     992              :  */
     993              : void
     994       155214 : UnregisterExprContextCallback(ExprContext *econtext,
     995              :                               ExprContextCallbackFunction function,
     996              :                               Datum arg)
     997              : {
     998              :     ExprContext_CB **prev_callback;
     999              :     ExprContext_CB *ecxt_callback;
    1000              : 
    1001       155214 :     prev_callback = &econtext->ecxt_callbacks;
    1002              : 
    1003       435731 :     while ((ecxt_callback = *prev_callback) != NULL)
    1004              :     {
    1005       280517 :         if (ecxt_callback->function == function && ecxt_callback->arg == arg)
    1006              :         {
    1007       155214 :             *prev_callback = ecxt_callback->next;
    1008       155214 :             pfree(ecxt_callback);
    1009              :         }
    1010              :         else
    1011       125303 :             prev_callback = &ecxt_callback->next;
    1012              :     }
    1013       155214 : }
    1014              : 
    1015              : /*
    1016              :  * Call all the shutdown callbacks registered in an ExprContext.
    1017              :  *
    1018              :  * The callback list is emptied (important in case this is only a rescan
    1019              :  * reset, and not deletion of the ExprContext).
    1020              :  *
    1021              :  * If isCommit is false, just clean the callback list but don't call 'em.
    1022              :  * (See comment for FreeExprContext.)
    1023              :  */
    1024              : static void
    1025      4786771 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
    1026              : {
    1027              :     ExprContext_CB *ecxt_callback;
    1028              :     MemoryContext oldcontext;
    1029              : 
    1030              :     /* Fast path in normal case where there's nothing to do. */
    1031      4786771 :     if (econtext->ecxt_callbacks == NULL)
    1032      4768415 :         return;
    1033              : 
    1034              :     /*
    1035              :      * Call the callbacks in econtext's per-tuple context.  This ensures that
    1036              :      * any memory they might leak will get cleaned up.
    1037              :      */
    1038        18356 :     oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
    1039              : 
    1040              :     /*
    1041              :      * Call each callback function in reverse registration order.
    1042              :      */
    1043        37095 :     while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
    1044              :     {
    1045        18739 :         econtext->ecxt_callbacks = ecxt_callback->next;
    1046        18739 :         if (isCommit)
    1047        18739 :             ecxt_callback->function(ecxt_callback->arg);
    1048        18739 :         pfree(ecxt_callback);
    1049              :     }
    1050              : 
    1051        18356 :     MemoryContextSwitchTo(oldcontext);
    1052              : }
    1053              : 
    1054              : /*
    1055              :  *      GetAttributeByName
    1056              :  *      GetAttributeByNum
    1057              :  *
    1058              :  *      These functions return the value of the requested attribute
    1059              :  *      out of the given tuple Datum.
    1060              :  *      C functions which take a tuple as an argument are expected
    1061              :  *      to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
    1062              :  *      Note: these are actually rather slow because they do a typcache
    1063              :  *      lookup on each call.
    1064              :  */
    1065              : Datum
    1066           24 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
    1067              : {
    1068              :     AttrNumber  attrno;
    1069              :     Datum       result;
    1070              :     Oid         tupType;
    1071              :     int32       tupTypmod;
    1072              :     TupleDesc   tupDesc;
    1073              :     HeapTupleData tmptup;
    1074              :     int         i;
    1075              : 
    1076           24 :     if (attname == NULL)
    1077            0 :         elog(ERROR, "invalid attribute name");
    1078              : 
    1079           24 :     if (isNull == NULL)
    1080            0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1081              : 
    1082           24 :     if (tuple == NULL)
    1083              :     {
    1084              :         /* Kinda bogus but compatible with old behavior... */
    1085            0 :         *isNull = true;
    1086            0 :         return (Datum) 0;
    1087              :     }
    1088              : 
    1089           24 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1090           24 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1091           24 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1092              : 
    1093           24 :     attrno = InvalidAttrNumber;
    1094           96 :     for (i = 0; i < tupDesc->natts; i++)
    1095              :     {
    1096           96 :         Form_pg_attribute att = TupleDescAttr(tupDesc, i);
    1097              : 
    1098           96 :         if (namestrcmp(&(att->attname), attname) == 0)
    1099              :         {
    1100           24 :             attrno = att->attnum;
    1101           24 :             break;
    1102              :         }
    1103              :     }
    1104              : 
    1105           24 :     if (attrno == InvalidAttrNumber)
    1106            0 :         elog(ERROR, "attribute \"%s\" does not exist", attname);
    1107              : 
    1108              :     /*
    1109              :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1110              :      * the fields in the struct just in case user tries to inspect system
    1111              :      * columns.
    1112              :      */
    1113           24 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1114           24 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1115           24 :     tmptup.t_tableOid = InvalidOid;
    1116           24 :     tmptup.t_data = tuple;
    1117              : 
    1118           24 :     result = heap_getattr(&tmptup,
    1119              :                           attrno,
    1120              :                           tupDesc,
    1121              :                           isNull);
    1122              : 
    1123           24 :     ReleaseTupleDesc(tupDesc);
    1124              : 
    1125           24 :     return result;
    1126              : }
    1127              : 
    1128              : Datum
    1129            0 : GetAttributeByNum(HeapTupleHeader tuple,
    1130              :                   AttrNumber attrno,
    1131              :                   bool *isNull)
    1132              : {
    1133              :     Datum       result;
    1134              :     Oid         tupType;
    1135              :     int32       tupTypmod;
    1136              :     TupleDesc   tupDesc;
    1137              :     HeapTupleData tmptup;
    1138              : 
    1139            0 :     if (!AttributeNumberIsValid(attrno))
    1140            0 :         elog(ERROR, "invalid attribute number %d", attrno);
    1141              : 
    1142            0 :     if (isNull == NULL)
    1143            0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1144              : 
    1145            0 :     if (tuple == NULL)
    1146              :     {
    1147              :         /* Kinda bogus but compatible with old behavior... */
    1148            0 :         *isNull = true;
    1149            0 :         return (Datum) 0;
    1150              :     }
    1151              : 
    1152            0 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1153            0 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1154            0 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1155              : 
    1156              :     /*
    1157              :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1158              :      * the fields in the struct just in case user tries to inspect system
    1159              :      * columns.
    1160              :      */
    1161            0 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1162            0 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1163            0 :     tmptup.t_tableOid = InvalidOid;
    1164            0 :     tmptup.t_data = tuple;
    1165              : 
    1166            0 :     result = heap_getattr(&tmptup,
    1167              :                           attrno,
    1168              :                           tupDesc,
    1169              :                           isNull);
    1170              : 
    1171            0 :     ReleaseTupleDesc(tupDesc);
    1172              : 
    1173            0 :     return result;
    1174              : }
    1175              : 
    1176              : /*
    1177              :  * Number of items in a tlist (including any resjunk items!)
    1178              :  */
    1179              : int
    1180      1697537 : ExecTargetListLength(List *targetlist)
    1181              : {
    1182              :     /* This used to be more complex, but fjoins are dead */
    1183      1697537 :     return list_length(targetlist);
    1184              : }
    1185              : 
    1186              : /*
    1187              :  * Number of items in a tlist, not including any resjunk items
    1188              :  */
    1189              : int
    1190       492589 : ExecCleanTargetListLength(List *targetlist)
    1191              : {
    1192       492589 :     int         len = 0;
    1193              :     ListCell   *tl;
    1194              : 
    1195      1588898 :     foreach(tl, targetlist)
    1196              :     {
    1197      1096309 :         TargetEntry *curTle = lfirst_node(TargetEntry, tl);
    1198              : 
    1199      1096309 :         if (!curTle->resjunk)
    1200       674182 :             len++;
    1201              :     }
    1202       492589 :     return len;
    1203              : }
    1204              : 
    1205              : /*
    1206              :  * Return a relInfo's tuple slot for a trigger's OLD tuples.
    1207              :  */
    1208              : TupleTableSlot *
    1209       415711 : ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
    1210              : {
    1211       415711 :     if (relInfo->ri_TrigOldSlot == NULL)
    1212              :     {
    1213         6704 :         Relation    rel = relInfo->ri_RelationDesc;
    1214         6704 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1215              : 
    1216         6704 :         relInfo->ri_TrigOldSlot =
    1217         6704 :             ExecInitExtraTupleSlot(estate,
    1218              :                                    RelationGetDescr(rel),
    1219              :                                    table_slot_callbacks(rel));
    1220              : 
    1221         6704 :         MemoryContextSwitchTo(oldcontext);
    1222              :     }
    1223              : 
    1224       415711 :     return relInfo->ri_TrigOldSlot;
    1225              : }
    1226              : 
    1227              : /*
    1228              :  * Return a relInfo's tuple slot for a trigger's NEW tuples.
    1229              :  */
    1230              : TupleTableSlot *
    1231         2342 : ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
    1232              : {
    1233         2342 :     if (relInfo->ri_TrigNewSlot == NULL)
    1234              :     {
    1235         1458 :         Relation    rel = relInfo->ri_RelationDesc;
    1236         1458 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1237              : 
    1238         1458 :         relInfo->ri_TrigNewSlot =
    1239         1458 :             ExecInitExtraTupleSlot(estate,
    1240              :                                    RelationGetDescr(rel),
    1241              :                                    table_slot_callbacks(rel));
    1242              : 
    1243         1458 :         MemoryContextSwitchTo(oldcontext);
    1244              :     }
    1245              : 
    1246         2342 :     return relInfo->ri_TrigNewSlot;
    1247              : }
    1248              : 
    1249              : /*
    1250              :  * Return a relInfo's tuple slot for processing returning tuples.
    1251              :  */
    1252              : TupleTableSlot *
    1253          809 : ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
    1254              : {
    1255          809 :     if (relInfo->ri_ReturningSlot == NULL)
    1256              :     {
    1257          435 :         Relation    rel = relInfo->ri_RelationDesc;
    1258          435 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1259              : 
    1260          435 :         relInfo->ri_ReturningSlot =
    1261          435 :             ExecInitExtraTupleSlot(estate,
    1262              :                                    RelationGetDescr(rel),
    1263              :                                    table_slot_callbacks(rel));
    1264              : 
    1265          435 :         MemoryContextSwitchTo(oldcontext);
    1266              :     }
    1267              : 
    1268          809 :     return relInfo->ri_ReturningSlot;
    1269              : }
    1270              : 
    1271              : /*
    1272              :  * Return a relInfo's all-NULL tuple slot for processing returning tuples.
    1273              :  *
    1274              :  * Note: this slot is intentionally filled with NULLs in every column, and
    1275              :  * should be considered read-only --- the caller must not update it.
    1276              :  */
    1277              : TupleTableSlot *
    1278          212 : ExecGetAllNullSlot(EState *estate, ResultRelInfo *relInfo)
    1279              : {
    1280          212 :     if (relInfo->ri_AllNullSlot == NULL)
    1281              :     {
    1282          146 :         Relation    rel = relInfo->ri_RelationDesc;
    1283          146 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1284              :         TupleTableSlot *slot;
    1285              : 
    1286          146 :         slot = ExecInitExtraTupleSlot(estate,
    1287              :                                       RelationGetDescr(rel),
    1288              :                                       table_slot_callbacks(rel));
    1289          146 :         ExecStoreAllNullTuple(slot);
    1290              : 
    1291          146 :         relInfo->ri_AllNullSlot = slot;
    1292              : 
    1293          146 :         MemoryContextSwitchTo(oldcontext);
    1294              :     }
    1295              : 
    1296          212 :     return relInfo->ri_AllNullSlot;
    1297              : }
    1298              : 
    1299              : /*
    1300              :  * Return the map needed to convert given child result relation's tuples to
    1301              :  * the rowtype of the query's main target ("root") relation.  Note that a
    1302              :  * NULL result is valid and means that no conversion is needed.
    1303              :  */
    1304              : TupleConversionMap *
    1305        45276 : ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
    1306              : {
    1307              :     /* If we didn't already do so, compute the map for this child. */
    1308        45276 :     if (!resultRelInfo->ri_ChildToRootMapValid)
    1309              :     {
    1310         1128 :         ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
    1311              : 
    1312         1128 :         if (rootRelInfo)
    1313          881 :             resultRelInfo->ri_ChildToRootMap =
    1314          881 :                 convert_tuples_by_name(RelationGetDescr(resultRelInfo->ri_RelationDesc),
    1315          881 :                                        RelationGetDescr(rootRelInfo->ri_RelationDesc));
    1316              :         else                    /* this isn't a child result rel */
    1317          247 :             resultRelInfo->ri_ChildToRootMap = NULL;
    1318              : 
    1319         1128 :         resultRelInfo->ri_ChildToRootMapValid = true;
    1320              :     }
    1321              : 
    1322        45276 :     return resultRelInfo->ri_ChildToRootMap;
    1323              : }
    1324              : 
    1325              : /*
    1326              :  * Returns the map needed to convert given root result relation's tuples to
    1327              :  * the rowtype of the given child relation.  Note that a NULL result is valid
    1328              :  * and means that no conversion is needed.
    1329              :  */
    1330              : TupleConversionMap *
    1331       637863 : ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
    1332              : {
    1333              :     /* Mustn't get called for a non-child result relation. */
    1334              :     Assert(resultRelInfo->ri_RootResultRelInfo);
    1335              : 
    1336              :     /* If we didn't already do so, compute the map for this child. */
    1337       637863 :     if (!resultRelInfo->ri_RootToChildMapValid)
    1338              :     {
    1339         6494 :         ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
    1340         6494 :         TupleDesc   indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
    1341         6494 :         TupleDesc   outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
    1342         6494 :         Relation    childrel = resultRelInfo->ri_RelationDesc;
    1343              :         AttrMap    *attrMap;
    1344              :         MemoryContext oldcontext;
    1345              : 
    1346              :         /*
    1347              :          * When this child table is not a partition (!relispartition), it may
    1348              :          * have columns that are not present in the root table, which we ask
    1349              :          * to ignore by passing true for missing_ok.
    1350              :          */
    1351         6494 :         oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1352         6494 :         attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
    1353         6494 :                                                !childrel->rd_rel->relispartition);
    1354         6494 :         if (attrMap)
    1355         1030 :             resultRelInfo->ri_RootToChildMap =
    1356         1030 :                 convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
    1357         6494 :         MemoryContextSwitchTo(oldcontext);
    1358         6494 :         resultRelInfo->ri_RootToChildMapValid = true;
    1359              :     }
    1360              : 
    1361       637863 :     return resultRelInfo->ri_RootToChildMap;
    1362              : }
    1363              : 
    1364              : /* Return a bitmap representing columns being inserted */
    1365              : Bitmapset *
    1366          943 : ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
    1367              : {
    1368          943 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
    1369              : 
    1370          943 :     if (perminfo == NULL)
    1371            0 :         return NULL;
    1372              : 
    1373              :     /* Map the columns to child's attribute numbers if needed. */
    1374          943 :     if (relinfo->ri_RootResultRelInfo)
    1375              :     {
    1376           47 :         TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
    1377              : 
    1378           47 :         if (map)
    1379            2 :             return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
    1380              :     }
    1381              : 
    1382          941 :     return perminfo->insertedCols;
    1383              : }
    1384              : 
    1385              : /* Return a bitmap representing columns being updated */
    1386              : Bitmapset *
    1387        31990 : ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1388              : {
    1389        31990 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
    1390              : 
    1391        31990 :     if (perminfo == NULL)
    1392            0 :         return NULL;
    1393              : 
    1394              :     /* Map the columns to child's attribute numbers if needed. */
    1395        31990 :     if (relinfo->ri_RootResultRelInfo)
    1396              :     {
    1397         1120 :         TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
    1398              : 
    1399         1120 :         if (map)
    1400          321 :             return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
    1401              :     }
    1402              : 
    1403        31669 :     return perminfo->updatedCols;
    1404              : }
    1405              : 
    1406              : /* Return a bitmap representing generated columns being updated */
    1407              : Bitmapset *
    1408        30924 : ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1409              : {
    1410              :     /* Compute the info if we didn't already */
    1411        30924 :     if (!relinfo->ri_extraUpdatedCols_valid)
    1412        30794 :         ExecInitGenerated(relinfo, estate, CMD_UPDATE);
    1413        30924 :     return relinfo->ri_extraUpdatedCols;
    1414              : }
    1415              : 
    1416              : /*
    1417              :  * Return columns being updated, including generated columns
    1418              :  *
    1419              :  * The bitmap is allocated in per-tuple memory context. It's up to the caller to
    1420              :  * copy it into a different context with the appropriate lifespan, if needed.
    1421              :  */
    1422              : Bitmapset *
    1423         8666 : ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
    1424              : {
    1425              :     Bitmapset  *ret;
    1426              :     MemoryContext oldcxt;
    1427              : 
    1428         8666 :     oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
    1429              : 
    1430         8666 :     ret = bms_union(ExecGetUpdatedCols(relinfo, estate),
    1431         8666 :                     ExecGetExtraUpdatedCols(relinfo, estate));
    1432              : 
    1433         8666 :     MemoryContextSwitchTo(oldcxt);
    1434              : 
    1435         8666 :     return ret;
    1436              : }
    1437              : 
    1438              : /*
    1439              :  * GetResultRTEPermissionInfo
    1440              :  *      Looks up RTEPermissionInfo for ExecGet*Cols() routines
    1441              :  */
    1442              : static RTEPermissionInfo *
    1443        33115 : GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
    1444              : {
    1445              :     Index       rti;
    1446              :     RangeTblEntry *rte;
    1447        33115 :     RTEPermissionInfo *perminfo = NULL;
    1448              : 
    1449        33115 :     if (relinfo->ri_RootResultRelInfo)
    1450              :     {
    1451              :         /*
    1452              :          * For inheritance child result relations (a partition routing target
    1453              :          * of an INSERT or a child UPDATE target), this returns the root
    1454              :          * parent's RTE to fetch the RTEPermissionInfo because that's the only
    1455              :          * one that has one assigned.
    1456              :          */
    1457         1223 :         rti = relinfo->ri_RootResultRelInfo->ri_RangeTableIndex;
    1458              :     }
    1459        31892 :     else if (relinfo->ri_RangeTableIndex != 0)
    1460              :     {
    1461              :         /*
    1462              :          * Non-child result relation should have their own RTEPermissionInfo.
    1463              :          */
    1464        31892 :         rti = relinfo->ri_RangeTableIndex;
    1465              :     }
    1466              :     else
    1467              :     {
    1468              :         /*
    1469              :          * The relation isn't in the range table and it isn't a partition
    1470              :          * routing target.  This ResultRelInfo must've been created only for
    1471              :          * firing triggers and the relation is not being inserted into.  (See
    1472              :          * ExecGetTriggerResultRel.)
    1473              :          */
    1474            0 :         rti = 0;
    1475              :     }
    1476              : 
    1477        33115 :     if (rti > 0)
    1478              :     {
    1479        33115 :         rte = exec_rt_fetch(rti, estate);
    1480        33115 :         perminfo = getRTEPermissionInfo(estate->es_rteperminfos, rte);
    1481              :     }
    1482              : 
    1483        33115 :     return perminfo;
    1484              : }
    1485              : 
    1486              : /*
    1487              :  * ExecGetResultRelCheckAsUser
    1488              :  *      Returns the user to modify passed-in result relation as
    1489              :  *
    1490              :  * The user is chosen by looking up the relation's or, if a child table, its
    1491              :  * root parent's RTEPermissionInfo.
    1492              :  */
    1493              : Oid
    1494          182 : ExecGetResultRelCheckAsUser(ResultRelInfo *relInfo, EState *estate)
    1495              : {
    1496          182 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relInfo, estate);
    1497              : 
    1498              :     /* XXX - maybe ok to return GetUserId() in this case? */
    1499          182 :     if (perminfo == NULL)
    1500            0 :         elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
    1501              :              RelationGetRelid(relInfo->ri_RelationDesc));
    1502              : 
    1503          182 :     return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
    1504              : }
        

Generated by: LCOV version 2.0-1