LCOV - code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 294 335 87.8 %
Date: 2020-06-05 19:06:29 Functions: 31 34 91.2 %
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-2020, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/executor/execUtils.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : /*
      16             :  * INTERFACE ROUTINES
      17             :  *      CreateExecutorState     Create/delete executor working state
      18             :  *      FreeExecutorState
      19             :  *      CreateExprContext
      20             :  *      CreateStandaloneExprContext
      21             :  *      FreeExprContext
      22             :  *      ReScanExprContext
      23             :  *
      24             :  *      ExecAssignExprContext   Common code for plan node init routines.
      25             :  *      etc
      26             :  *
      27             :  *      ExecOpenScanRelation    Common code for scan node init routines.
      28             :  *
      29             :  *      ExecInitRangeTable      Set up executor's range-table-related data.
      30             :  *
      31             :  *      ExecGetRangeTableRelation       Fetch Relation for a rangetable entry.
      32             :  *
      33             :  *      executor_errposition    Report syntactic position of an error.
      34             :  *
      35             :  *      RegisterExprContextCallback    Register function shutdown callback
      36             :  *      UnregisterExprContextCallback  Deregister function shutdown callback
      37             :  *
      38             :  *      GetAttributeByName      Runtime extraction of columns from tuples.
      39             :  *      GetAttributeByNum
      40             :  *
      41             :  *   NOTES
      42             :  *      This file has traditionally been the place to stick misc.
      43             :  *      executor support stuff that doesn't really go anyplace else.
      44             :  */
      45             : 
      46             : #include "postgres.h"
      47             : 
      48             : #include "access/parallel.h"
      49             : #include "access/relscan.h"
      50             : #include "access/table.h"
      51             : #include "access/tableam.h"
      52             : #include "access/transam.h"
      53             : #include "executor/executor.h"
      54             : #include "jit/jit.h"
      55             : #include "mb/pg_wchar.h"
      56             : #include "miscadmin.h"
      57             : #include "nodes/nodeFuncs.h"
      58             : #include "parser/parsetree.h"
      59             : #include "partitioning/partdesc.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, Index varno, TupleDesc tupdesc);
      68             : static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
      69             : 
      70             : 
      71             : /* ----------------------------------------------------------------
      72             :  *               Executor state and memory management functions
      73             :  * ----------------------------------------------------------------
      74             :  */
      75             : 
      76             : /* ----------------
      77             :  *      CreateExecutorState
      78             :  *
      79             :  *      Create and initialize an EState node, which is the root of
      80             :  *      working storage for an entire Executor invocation.
      81             :  *
      82             :  * Principally, this creates the per-query memory context that will be
      83             :  * used to hold all working data that lives till the end of the query.
      84             :  * Note that the per-query context will become a child of the caller's
      85             :  * CurrentMemoryContext.
      86             :  * ----------------
      87             :  */
      88             : EState *
      89      570832 : CreateExecutorState(void)
      90             : {
      91             :     EState     *estate;
      92             :     MemoryContext qcontext;
      93             :     MemoryContext oldcontext;
      94             : 
      95             :     /*
      96             :      * Create the per-query context for this Executor run.
      97             :      */
      98      570832 :     qcontext = AllocSetContextCreate(CurrentMemoryContext,
      99             :                                      "ExecutorState",
     100             :                                      ALLOCSET_DEFAULT_SIZES);
     101             : 
     102             :     /*
     103             :      * Make the EState node within the per-query context.  This way, we don't
     104             :      * need a separate pfree() operation for it at shutdown.
     105             :      */
     106      570832 :     oldcontext = MemoryContextSwitchTo(qcontext);
     107             : 
     108      570832 :     estate = makeNode(EState);
     109             : 
     110             :     /*
     111             :      * Initialize all fields of the Executor State structure
     112             :      */
     113      570832 :     estate->es_direction = ForwardScanDirection;
     114      570832 :     estate->es_snapshot = InvalidSnapshot;   /* caller must initialize this */
     115      570832 :     estate->es_crosscheck_snapshot = InvalidSnapshot;    /* no crosscheck */
     116      570832 :     estate->es_range_table = NIL;
     117      570832 :     estate->es_range_table_size = 0;
     118      570832 :     estate->es_relations = NULL;
     119      570832 :     estate->es_rowmarks = NULL;
     120      570832 :     estate->es_plannedstmt = NULL;
     121             : 
     122      570832 :     estate->es_junkFilter = NULL;
     123             : 
     124      570832 :     estate->es_output_cid = (CommandId) 0;
     125             : 
     126      570832 :     estate->es_result_relations = NULL;
     127      570832 :     estate->es_num_result_relations = 0;
     128      570832 :     estate->es_result_relation_info = NULL;
     129             : 
     130      570832 :     estate->es_root_result_relations = NULL;
     131      570832 :     estate->es_num_root_result_relations = 0;
     132             : 
     133      570832 :     estate->es_tuple_routing_result_relations = NIL;
     134             : 
     135      570832 :     estate->es_trig_target_relations = NIL;
     136             : 
     137      570832 :     estate->es_param_list_info = NULL;
     138      570832 :     estate->es_param_exec_vals = NULL;
     139             : 
     140      570832 :     estate->es_queryEnv = NULL;
     141             : 
     142      570832 :     estate->es_query_cxt = qcontext;
     143             : 
     144      570832 :     estate->es_tupleTable = NIL;
     145             : 
     146      570832 :     estate->es_processed = 0;
     147             : 
     148      570832 :     estate->es_top_eflags = 0;
     149      570832 :     estate->es_instrument = 0;
     150      570832 :     estate->es_finished = false;
     151             : 
     152      570832 :     estate->es_exprcontexts = NIL;
     153             : 
     154      570832 :     estate->es_subplanstates = NIL;
     155             : 
     156      570832 :     estate->es_auxmodifytables = NIL;
     157             : 
     158      570832 :     estate->es_per_tuple_exprcontext = NULL;
     159             : 
     160      570832 :     estate->es_sourceText = NULL;
     161             : 
     162      570832 :     estate->es_use_parallel_mode = false;
     163             : 
     164      570832 :     estate->es_jit_flags = 0;
     165      570832 :     estate->es_jit = NULL;
     166             : 
     167             :     /*
     168             :      * Return the executor state structure
     169             :      */
     170      570832 :     MemoryContextSwitchTo(oldcontext);
     171             : 
     172      570832 :     return estate;
     173             : }
     174             : 
     175             : /* ----------------
     176             :  *      FreeExecutorState
     177             :  *
     178             :  *      Release an EState along with all remaining working storage.
     179             :  *
     180             :  * Note: this is not responsible for releasing non-memory resources, such as
     181             :  * open relations or buffer pins.  But it will shut down any still-active
     182             :  * ExprContexts within the EState and deallocate associated JITed expressions.
     183             :  * That is sufficient cleanup for situations where the EState has only been
     184             :  * used for expression evaluation, and not to run a complete Plan.
     185             :  *
     186             :  * This can be called in any memory context ... so long as it's not one
     187             :  * of the ones to be freed.
     188             :  * ----------------
     189             :  */
     190             : void
     191      555018 : FreeExecutorState(EState *estate)
     192             : {
     193             :     /*
     194             :      * Shut down and free any remaining ExprContexts.  We do this explicitly
     195             :      * to ensure that any remaining shutdown callbacks get called (since they
     196             :      * might need to release resources that aren't simply memory within the
     197             :      * per-query memory context).
     198             :      */
     199     1516304 :     while (estate->es_exprcontexts)
     200             :     {
     201             :         /*
     202             :          * XXX: seems there ought to be a faster way to implement this than
     203             :          * repeated list_delete(), no?
     204             :          */
     205      961286 :         FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
     206             :                         true);
     207             :         /* FreeExprContext removed the list link for us */
     208             :     }
     209             : 
     210             :     /* release JIT context, if allocated */
     211      555018 :     if (estate->es_jit)
     212             :     {
     213         924 :         jit_release_context(estate->es_jit);
     214         924 :         estate->es_jit = NULL;
     215             :     }
     216             : 
     217             :     /* release partition directory, if allocated */
     218      555018 :     if (estate->es_partition_directory)
     219             :     {
     220        2230 :         DestroyPartitionDirectory(estate->es_partition_directory);
     221        2230 :         estate->es_partition_directory = NULL;
     222             :     }
     223             : 
     224             :     /*
     225             :      * Free the per-query memory context, thereby releasing all working
     226             :      * memory, including the EState node itself.
     227             :      */
     228      555018 :     MemoryContextDelete(estate->es_query_cxt);
     229      555018 : }
     230             : 
     231             : /*
     232             :  * Internal implementation for CreateExprContext() and CreateWorkExprContext()
     233             :  * that allows control over the AllocSet parameters.
     234             :  */
     235             : static ExprContext *
     236     1050488 : CreateExprContextInternal(EState *estate, Size minContextSize,
     237             :                           Size initBlockSize, Size maxBlockSize)
     238             : {
     239             :     ExprContext *econtext;
     240             :     MemoryContext oldcontext;
     241             : 
     242             :     /* Create the ExprContext node within the per-query memory context */
     243     1050488 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     244             : 
     245     1050488 :     econtext = makeNode(ExprContext);
     246             : 
     247             :     /* Initialize fields of ExprContext */
     248     1050488 :     econtext->ecxt_scantuple = NULL;
     249     1050488 :     econtext->ecxt_innertuple = NULL;
     250     1050488 :     econtext->ecxt_outertuple = NULL;
     251             : 
     252     1050488 :     econtext->ecxt_per_query_memory = estate->es_query_cxt;
     253             : 
     254             :     /*
     255             :      * Create working memory for expression evaluation in this context.
     256             :      */
     257     1050488 :     econtext->ecxt_per_tuple_memory =
     258     1050488 :         AllocSetContextCreate(estate->es_query_cxt,
     259             :                               "ExprContext",
     260             :                               minContextSize,
     261             :                               initBlockSize,
     262             :                               maxBlockSize);
     263             : 
     264     1050488 :     econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
     265     1050488 :     econtext->ecxt_param_list_info = estate->es_param_list_info;
     266             : 
     267     1050488 :     econtext->ecxt_aggvalues = NULL;
     268     1050488 :     econtext->ecxt_aggnulls = NULL;
     269             : 
     270     1050488 :     econtext->caseValue_datum = (Datum) 0;
     271     1050488 :     econtext->caseValue_isNull = true;
     272             : 
     273     1050488 :     econtext->domainValue_datum = (Datum) 0;
     274     1050488 :     econtext->domainValue_isNull = true;
     275             : 
     276     1050488 :     econtext->ecxt_estate = estate;
     277             : 
     278     1050488 :     econtext->ecxt_callbacks = NULL;
     279             : 
     280             :     /*
     281             :      * Link the ExprContext into the EState to ensure it is shut down when the
     282             :      * EState is freed.  Because we use lcons(), shutdowns will occur in
     283             :      * reverse order of creation, which may not be essential but can't hurt.
     284             :      */
     285     1050488 :     estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
     286             : 
     287     1050488 :     MemoryContextSwitchTo(oldcontext);
     288             : 
     289     1050488 :     return econtext;
     290             : }
     291             : 
     292             : /* ----------------
     293             :  *      CreateExprContext
     294             :  *
     295             :  *      Create a context for expression evaluation within an EState.
     296             :  *
     297             :  * An executor run may require multiple ExprContexts (we usually make one
     298             :  * for each Plan node, and a separate one for per-output-tuple processing
     299             :  * such as constraint checking).  Each ExprContext has its own "per-tuple"
     300             :  * memory context.
     301             :  *
     302             :  * Note we make no assumption about the caller's memory context.
     303             :  * ----------------
     304             :  */
     305             : ExprContext *
     306     1047532 : CreateExprContext(EState *estate)
     307             : {
     308     1047532 :     return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES);
     309             : }
     310             : 
     311             : 
     312             : /* ----------------
     313             :  *      CreateWorkExprContext
     314             :  *
     315             :  * Like CreateExprContext, but specifies the AllocSet sizes to be reasonable
     316             :  * in proportion to work_mem. If the maximum block allocation size is too
     317             :  * large, it's easy to skip right past work_mem with a single allocation.
     318             :  * ----------------
     319             :  */
     320             : ExprContext *
     321        2956 : CreateWorkExprContext(EState *estate)
     322             : {
     323        2956 :     Size        minContextSize = ALLOCSET_DEFAULT_MINSIZE;
     324        2956 :     Size        initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
     325        2956 :     Size        maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
     326             : 
     327             :     /* choose the maxBlockSize to be no larger than 1/16 of work_mem */
     328       18096 :     while (16 * maxBlockSize > work_mem * 1024L)
     329       15140 :         maxBlockSize >>= 1;
     330             : 
     331        2956 :     if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
     332          52 :         maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
     333             : 
     334        2956 :     return CreateExprContextInternal(estate, minContextSize,
     335             :                                      initBlockSize, maxBlockSize);
     336             : }
     337             : 
     338             : /* ----------------
     339             :  *      CreateStandaloneExprContext
     340             :  *
     341             :  *      Create a context for standalone expression evaluation.
     342             :  *
     343             :  * An ExprContext made this way can be used for evaluation of expressions
     344             :  * that contain no Params, subplans, or Var references (it might work to
     345             :  * put tuple references into the scantuple field, but it seems unwise).
     346             :  *
     347             :  * The ExprContext struct is allocated in the caller's current memory
     348             :  * context, which also becomes its "per query" context.
     349             :  *
     350             :  * It is caller's responsibility to free the ExprContext when done,
     351             :  * or at least ensure that any shutdown callbacks have been called
     352             :  * (ReScanExprContext() is suitable).  Otherwise, non-memory resources
     353             :  * might be leaked.
     354             :  * ----------------
     355             :  */
     356             : ExprContext *
     357        6010 : CreateStandaloneExprContext(void)
     358             : {
     359             :     ExprContext *econtext;
     360             : 
     361             :     /* Create the ExprContext node within the caller's memory context */
     362        6010 :     econtext = makeNode(ExprContext);
     363             : 
     364             :     /* Initialize fields of ExprContext */
     365        6010 :     econtext->ecxt_scantuple = NULL;
     366        6010 :     econtext->ecxt_innertuple = NULL;
     367        6010 :     econtext->ecxt_outertuple = NULL;
     368             : 
     369        6010 :     econtext->ecxt_per_query_memory = CurrentMemoryContext;
     370             : 
     371             :     /*
     372             :      * Create working memory for expression evaluation in this context.
     373             :      */
     374        6010 :     econtext->ecxt_per_tuple_memory =
     375        6010 :         AllocSetContextCreate(CurrentMemoryContext,
     376             :                               "ExprContext",
     377             :                               ALLOCSET_DEFAULT_SIZES);
     378             : 
     379        6010 :     econtext->ecxt_param_exec_vals = NULL;
     380        6010 :     econtext->ecxt_param_list_info = NULL;
     381             : 
     382        6010 :     econtext->ecxt_aggvalues = NULL;
     383        6010 :     econtext->ecxt_aggnulls = NULL;
     384             : 
     385        6010 :     econtext->caseValue_datum = (Datum) 0;
     386        6010 :     econtext->caseValue_isNull = true;
     387             : 
     388        6010 :     econtext->domainValue_datum = (Datum) 0;
     389        6010 :     econtext->domainValue_isNull = true;
     390             : 
     391        6010 :     econtext->ecxt_estate = NULL;
     392             : 
     393        6010 :     econtext->ecxt_callbacks = NULL;
     394             : 
     395        6010 :     return econtext;
     396             : }
     397             : 
     398             : /* ----------------
     399             :  *      FreeExprContext
     400             :  *
     401             :  *      Free an expression context, including calling any remaining
     402             :  *      shutdown callbacks.
     403             :  *
     404             :  * Since we free the temporary context used for expression evaluation,
     405             :  * any previously computed pass-by-reference expression result will go away!
     406             :  *
     407             :  * If isCommit is false, we are being called in error cleanup, and should
     408             :  * not call callbacks but only release memory.  (It might be better to call
     409             :  * the callbacks and pass the isCommit flag to them, but that would require
     410             :  * more invasive code changes than currently seems justified.)
     411             :  *
     412             :  * Note we make no assumption about the caller's memory context.
     413             :  * ----------------
     414             :  */
     415             : void
     416     1032100 : FreeExprContext(ExprContext *econtext, bool isCommit)
     417             : {
     418             :     EState     *estate;
     419             : 
     420             :     /* Call any registered callbacks */
     421     1032100 :     ShutdownExprContext(econtext, isCommit);
     422             :     /* And clean up the memory used */
     423     1032100 :     MemoryContextDelete(econtext->ecxt_per_tuple_memory);
     424             :     /* Unlink self from owning EState, if any */
     425     1032100 :     estate = econtext->ecxt_estate;
     426     1032100 :     if (estate)
     427     1032100 :         estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
     428             :                                                   econtext);
     429             :     /* And delete the ExprContext node */
     430     1032100 :     pfree(econtext);
     431     1032100 : }
     432             : 
     433             : /*
     434             :  * ReScanExprContext
     435             :  *
     436             :  *      Reset an expression context in preparation for a rescan of its
     437             :  *      plan node.  This requires calling any registered shutdown callbacks,
     438             :  *      since any partially complete set-returning-functions must be canceled.
     439             :  *
     440             :  * Note we make no assumption about the caller's memory context.
     441             :  */
     442             : void
     443     9531756 : ReScanExprContext(ExprContext *econtext)
     444             : {
     445             :     /* Call any registered callbacks */
     446     9531756 :     ShutdownExprContext(econtext, true);
     447             :     /* And clean up the memory used */
     448     9531756 :     MemoryContextReset(econtext->ecxt_per_tuple_memory);
     449     9531756 : }
     450             : 
     451             : /*
     452             :  * Build a per-output-tuple ExprContext for an EState.
     453             :  *
     454             :  * This is normally invoked via GetPerTupleExprContext() macro,
     455             :  * not directly.
     456             :  */
     457             : ExprContext *
     458      217858 : MakePerTupleExprContext(EState *estate)
     459             : {
     460      217858 :     if (estate->es_per_tuple_exprcontext == NULL)
     461      217858 :         estate->es_per_tuple_exprcontext = CreateExprContext(estate);
     462             : 
     463      217858 :     return estate->es_per_tuple_exprcontext;
     464             : }
     465             : 
     466             : 
     467             : /* ----------------------------------------------------------------
     468             :  *               miscellaneous node-init support functions
     469             :  *
     470             :  * Note: all of these are expected to be called with CurrentMemoryContext
     471             :  * equal to the per-query memory context.
     472             :  * ----------------------------------------------------------------
     473             :  */
     474             : 
     475             : /* ----------------
     476             :  *      ExecAssignExprContext
     477             :  *
     478             :  *      This initializes the ps_ExprContext field.  It is only necessary
     479             :  *      to do this for nodes which use ExecQual or ExecProject
     480             :  *      because those routines require an econtext. Other nodes that
     481             :  *      don't have to evaluate expressions don't need to do this.
     482             :  * ----------------
     483             :  */
     484             : void
     485      748124 : ExecAssignExprContext(EState *estate, PlanState *planstate)
     486             : {
     487      748124 :     planstate->ps_ExprContext = CreateExprContext(estate);
     488      748124 : }
     489             : 
     490             : /* ----------------
     491             :  *      ExecGetResultType
     492             :  * ----------------
     493             :  */
     494             : TupleDesc
     495      993226 : ExecGetResultType(PlanState *planstate)
     496             : {
     497      993226 :     return planstate->ps_ResultTupleDesc;
     498             : }
     499             : 
     500             : /*
     501             :  * ExecGetResultSlotOps - information about node's type of result slot
     502             :  */
     503             : const TupleTableSlotOps *
     504      376314 : ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
     505             : {
     506      376314 :     if (planstate->resultopsset && planstate->resultops)
     507             :     {
     508      375490 :         if (isfixed)
     509      341422 :             *isfixed = planstate->resultopsfixed;
     510      375490 :         return planstate->resultops;
     511             :     }
     512             : 
     513         824 :     if (isfixed)
     514             :     {
     515         804 :         if (planstate->resultopsset)
     516         804 :             *isfixed = planstate->resultopsfixed;
     517           0 :         else if (planstate->ps_ResultTupleSlot)
     518           0 :             *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
     519             :         else
     520           0 :             *isfixed = false;
     521             :     }
     522             : 
     523         824 :     if (!planstate->ps_ResultTupleSlot)
     524         824 :         return &TTSOpsVirtual;
     525             : 
     526           0 :     return planstate->ps_ResultTupleSlot->tts_ops;
     527             : }
     528             : 
     529             : 
     530             : /* ----------------
     531             :  *      ExecAssignProjectionInfo
     532             :  *
     533             :  * forms the projection information from the node's targetlist
     534             :  *
     535             :  * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
     536             :  * for a relation-scan node, can pass NULL for upper-level nodes
     537             :  * ----------------
     538             :  */
     539             : void
     540      481672 : ExecAssignProjectionInfo(PlanState *planstate,
     541             :                          TupleDesc inputDesc)
     542             : {
     543      481640 :     planstate->ps_ProjInfo =
     544      481672 :         ExecBuildProjectionInfo(planstate->plan->targetlist,
     545             :                                 planstate->ps_ExprContext,
     546             :                                 planstate->ps_ResultTupleSlot,
     547             :                                 planstate,
     548             :                                 inputDesc);
     549      481640 : }
     550             : 
     551             : 
     552             : /* ----------------
     553             :  *      ExecConditionalAssignProjectionInfo
     554             :  *
     555             :  * as ExecAssignProjectionInfo, but store NULL rather than building projection
     556             :  * info if no projection is required
     557             :  * ----------------
     558             :  */
     559             : void
     560      292694 : ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
     561             :                                     Index varno)
     562             : {
     563      292694 :     if (tlist_matches_tupdesc(planstate,
     564      292694 :                               planstate->plan->targetlist,
     565             :                               varno,
     566             :                               inputDesc))
     567             :     {
     568      126710 :         planstate->ps_ProjInfo = NULL;
     569      126710 :         planstate->resultopsset = planstate->scanopsset;
     570      126710 :         planstate->resultopsfixed = planstate->scanopsfixed;
     571      126710 :         planstate->resultops = planstate->scanops;
     572             :     }
     573             :     else
     574             :     {
     575      165984 :         if (!planstate->ps_ResultTupleSlot)
     576             :         {
     577      165984 :             ExecInitResultSlot(planstate, &TTSOpsVirtual);
     578      165984 :             planstate->resultops = &TTSOpsVirtual;
     579      165984 :             planstate->resultopsfixed = true;
     580      165984 :             planstate->resultopsset = true;
     581             :         }
     582      165984 :         ExecAssignProjectionInfo(planstate, inputDesc);
     583             :     }
     584      292694 : }
     585             : 
     586             : static bool
     587      292694 : tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
     588             : {
     589      292694 :     int         numattrs = tupdesc->natts;
     590             :     int         attrno;
     591      292694 :     ListCell   *tlist_item = list_head(tlist);
     592             : 
     593             :     /* Check the tlist attributes */
     594     1841840 :     for (attrno = 1; attrno <= numattrs; attrno++)
     595             :     {
     596     1709454 :         Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
     597             :         Var        *var;
     598             : 
     599     1709454 :         if (tlist_item == NULL)
     600       24332 :             return false;       /* tlist too short */
     601     1685122 :         var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
     602     1685122 :         if (!var || !IsA(var, Var))
     603       50998 :             return false;       /* tlist item not a Var */
     604             :         /* if these Asserts fail, planner messed up */
     605             :         Assert(var->varno == varno);
     606             :         Assert(var->varlevelsup == 0);
     607     1634124 :         if (var->varattno != attrno)
     608       84774 :             return false;       /* out of order */
     609     1549350 :         if (att_tup->attisdropped)
     610           0 :             return false;       /* table contains dropped columns */
     611     1549350 :         if (att_tup->atthasmissing)
     612         200 :             return false;       /* table contains cols with missing values */
     613             : 
     614             :         /*
     615             :          * Note: usually the Var's type should match the tupdesc exactly, but
     616             :          * in situations involving unions of columns that have different
     617             :          * typmods, the Var may have come from above the union and hence have
     618             :          * typmod -1.  This is a legitimate situation since the Var still
     619             :          * describes the column, just not as exactly as the tupdesc does. We
     620             :          * could change the planner to prevent it, but it'd then insert
     621             :          * projection steps just to convert from specific typmod to typmod -1,
     622             :          * which is pretty silly.
     623             :          */
     624     1549150 :         if (var->vartype != att_tup->atttypid ||
     625     1549146 :             (var->vartypmod != att_tup->atttypmod &&
     626           4 :              var->vartypmod != -1))
     627           4 :             return false;       /* type mismatch */
     628             : 
     629     1549146 :         tlist_item = lnext(tlist, tlist_item);
     630             :     }
     631             : 
     632      132386 :     if (tlist_item)
     633        5676 :         return false;           /* tlist too long */
     634             : 
     635      126710 :     return true;
     636             : }
     637             : 
     638             : /* ----------------
     639             :  *      ExecFreeExprContext
     640             :  *
     641             :  * A plan node's ExprContext should be freed explicitly during executor
     642             :  * shutdown because there may be shutdown callbacks to call.  (Other resources
     643             :  * made by the above routines, such as projection info, don't need to be freed
     644             :  * explicitly because they're just memory in the per-query memory context.)
     645             :  *
     646             :  * However ... there is no particular need to do it during ExecEndNode,
     647             :  * because FreeExecutorState will free any remaining ExprContexts within
     648             :  * the EState.  Letting FreeExecutorState do it allows the ExprContexts to
     649             :  * be freed in reverse order of creation, rather than order of creation as
     650             :  * will happen if we delete them here, which saves O(N^2) work in the list
     651             :  * cleanup inside FreeExprContext.
     652             :  * ----------------
     653             :  */
     654             : void
     655      635402 : ExecFreeExprContext(PlanState *planstate)
     656             : {
     657             :     /*
     658             :      * Per above discussion, don't actually delete the ExprContext. We do
     659             :      * unlink it from the plan node, though.
     660             :      */
     661      635402 :     planstate->ps_ExprContext = NULL;
     662      635402 : }
     663             : 
     664             : 
     665             : /* ----------------------------------------------------------------
     666             :  *                Scan node support
     667             :  * ----------------------------------------------------------------
     668             :  */
     669             : 
     670             : /* ----------------
     671             :  *      ExecAssignScanType
     672             :  * ----------------
     673             :  */
     674             : void
     675         320 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
     676             : {
     677         320 :     TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
     678             : 
     679         320 :     ExecSetSlotDescriptor(slot, tupDesc);
     680         320 : }
     681             : 
     682             : /* ----------------
     683             :  *      ExecCreateScanSlotFromOuterPlan
     684             :  * ----------------
     685             :  */
     686             : void
     687       69980 : ExecCreateScanSlotFromOuterPlan(EState *estate,
     688             :                                 ScanState *scanstate,
     689             :                                 const TupleTableSlotOps *tts_ops)
     690             : {
     691             :     PlanState  *outerPlan;
     692             :     TupleDesc   tupDesc;
     693             : 
     694       69980 :     outerPlan = outerPlanState(scanstate);
     695       69980 :     tupDesc = ExecGetResultType(outerPlan);
     696             : 
     697       69980 :     ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
     698       69980 : }
     699             : 
     700             : /* ----------------------------------------------------------------
     701             :  *      ExecRelationIsTargetRelation
     702             :  *
     703             :  *      Detect whether a relation (identified by rangetable index)
     704             :  *      is one of the target relations of the query.
     705             :  *
     706             :  * Note: This is currently no longer used in core.  We keep it around
     707             :  * because FDWs may wish to use it to determine if their foreign table
     708             :  * is a target relation.
     709             :  * ----------------------------------------------------------------
     710             :  */
     711             : bool
     712           0 : ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
     713             : {
     714             :     ResultRelInfo *resultRelInfos;
     715             :     int         i;
     716             : 
     717           0 :     resultRelInfos = estate->es_result_relations;
     718           0 :     for (i = 0; i < estate->es_num_result_relations; i++)
     719             :     {
     720           0 :         if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
     721           0 :             return true;
     722             :     }
     723           0 :     return false;
     724             : }
     725             : 
     726             : /* ----------------------------------------------------------------
     727             :  *      ExecOpenScanRelation
     728             :  *
     729             :  *      Open the heap relation to be scanned by a base-level scan plan node.
     730             :  *      This should be called during the node's ExecInit routine.
     731             :  * ----------------------------------------------------------------
     732             :  */
     733             : Relation
     734      249616 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
     735             : {
     736             :     Relation    rel;
     737             : 
     738             :     /* Open the relation. */
     739      249616 :     rel = ExecGetRangeTableRelation(estate, scanrelid);
     740             : 
     741             :     /*
     742             :      * Complain if we're attempting a scan of an unscannable relation, except
     743             :      * when the query won't actually be run.  This is a slightly klugy place
     744             :      * to do this, perhaps, but there is no better place.
     745             :      */
     746      249616 :     if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
     747      233784 :         !RelationIsScannable(rel))
     748           8 :         ereport(ERROR,
     749             :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
     750             :                  errmsg("materialized view \"%s\" has not been populated",
     751             :                         RelationGetRelationName(rel)),
     752             :                  errhint("Use the REFRESH MATERIALIZED VIEW command.")));
     753             : 
     754      249608 :     return rel;
     755             : }
     756             : 
     757             : /*
     758             :  * ExecInitRangeTable
     759             :  *      Set up executor's range-table-related data
     760             :  *
     761             :  * In addition to the range table proper, initialize arrays that are
     762             :  * indexed by rangetable index.
     763             :  */
     764             : void
     765      375992 : ExecInitRangeTable(EState *estate, List *rangeTable)
     766             : {
     767             :     /* Remember the range table List as-is */
     768      375992 :     estate->es_range_table = rangeTable;
     769             : 
     770             :     /* Set size of associated arrays */
     771      375992 :     estate->es_range_table_size = list_length(rangeTable);
     772             : 
     773             :     /*
     774             :      * Allocate an array to store an open Relation corresponding to each
     775             :      * rangetable entry, and initialize entries to NULL.  Relations are opened
     776             :      * and stored here as needed.
     777             :      */
     778      375992 :     estate->es_relations = (Relation *)
     779      375992 :         palloc0(estate->es_range_table_size * sizeof(Relation));
     780             : 
     781             :     /*
     782             :      * es_rowmarks is also parallel to the es_range_table, but it's allocated
     783             :      * only if needed.
     784             :      */
     785      375992 :     estate->es_rowmarks = NULL;
     786      375992 : }
     787             : 
     788             : /*
     789             :  * ExecGetRangeTableRelation
     790             :  *      Open the Relation for a range table entry, if not already done
     791             :  *
     792             :  * The Relations will be closed again in ExecEndPlan().
     793             :  */
     794             : Relation
     795      348416 : ExecGetRangeTableRelation(EState *estate, Index rti)
     796             : {
     797             :     Relation    rel;
     798             : 
     799             :     Assert(rti > 0 && rti <= estate->es_range_table_size);
     800             : 
     801      348416 :     rel = estate->es_relations[rti - 1];
     802      348416 :     if (rel == NULL)
     803             :     {
     804             :         /* First time through, so open the relation */
     805      320386 :         RangeTblEntry *rte = exec_rt_fetch(rti, estate);
     806             : 
     807             :         Assert(rte->rtekind == RTE_RELATION);
     808             : 
     809      320386 :         if (!IsParallelWorker())
     810             :         {
     811             :             /*
     812             :              * In a normal query, we should already have the appropriate lock,
     813             :              * but verify that through an Assert.  Since there's already an
     814             :              * Assert inside table_open that insists on holding some lock, it
     815             :              * seems sufficient to check this only when rellockmode is higher
     816             :              * than the minimum.
     817             :              */
     818      317682 :             rel = table_open(rte->relid, NoLock);
     819             :             Assert(rte->rellockmode == AccessShareLock ||
     820             :                    CheckRelationLockedByMe(rel, rte->rellockmode, false));
     821             :         }
     822             :         else
     823             :         {
     824             :             /*
     825             :              * If we are a parallel worker, we need to obtain our own local
     826             :              * lock on the relation.  This ensures sane behavior in case the
     827             :              * parent process exits before we do.
     828             :              */
     829        2704 :             rel = table_open(rte->relid, rte->rellockmode);
     830             :         }
     831             : 
     832      320386 :         estate->es_relations[rti - 1] = rel;
     833             :     }
     834             : 
     835      348416 :     return rel;
     836             : }
     837             : 
     838             : /*
     839             :  * UpdateChangedParamSet
     840             :  *      Add changed parameters to a plan node's chgParam set
     841             :  */
     842             : void
     843     4009006 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
     844             : {
     845             :     Bitmapset  *parmset;
     846             : 
     847             :     /*
     848             :      * The plan node only depends on params listed in its allParam set. Don't
     849             :      * include anything else into its chgParam set.
     850             :      */
     851     4009006 :     parmset = bms_intersect(node->plan->allParam, newchg);
     852             : 
     853             :     /*
     854             :      * Keep node->chgParam == NULL if there's not actually any members; this
     855             :      * allows the simplest possible tests in executor node files.
     856             :      */
     857     4009006 :     if (!bms_is_empty(parmset))
     858     3921124 :         node->chgParam = bms_join(node->chgParam, parmset);
     859             :     else
     860       87882 :         bms_free(parmset);
     861     4009006 : }
     862             : 
     863             : /*
     864             :  * executor_errposition
     865             :  *      Report an execution-time cursor position, if possible.
     866             :  *
     867             :  * This is expected to be used within an ereport() call.  The return value
     868             :  * is a dummy (always 0, in fact).
     869             :  *
     870             :  * The locations stored in parsetrees are byte offsets into the source string.
     871             :  * We have to convert them to 1-based character indexes for reporting to
     872             :  * clients.  (We do things this way to avoid unnecessary overhead in the
     873             :  * normal non-error case: computing character indexes would be much more
     874             :  * expensive than storing token offsets.)
     875             :  */
     876             : int
     877           0 : executor_errposition(EState *estate, int location)
     878             : {
     879             :     int         pos;
     880             : 
     881             :     /* No-op if location was not provided */
     882           0 :     if (location < 0)
     883           0 :         return 0;
     884             :     /* Can't do anything if source text is not available */
     885           0 :     if (estate == NULL || estate->es_sourceText == NULL)
     886           0 :         return 0;
     887             :     /* Convert offset to character number */
     888           0 :     pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
     889             :     /* And pass it to the ereport mechanism */
     890           0 :     return errposition(pos);
     891             : }
     892             : 
     893             : /*
     894             :  * Register a shutdown callback in an ExprContext.
     895             :  *
     896             :  * Shutdown callbacks will be called (in reverse order of registration)
     897             :  * when the ExprContext is deleted or rescanned.  This provides a hook
     898             :  * for functions called in the context to do any cleanup needed --- it's
     899             :  * particularly useful for functions returning sets.  Note that the
     900             :  * callback will *not* be called in the event that execution is aborted
     901             :  * by an error.
     902             :  */
     903             : void
     904     1516006 : RegisterExprContextCallback(ExprContext *econtext,
     905             :                             ExprContextCallbackFunction function,
     906             :                             Datum arg)
     907             : {
     908             :     ExprContext_CB *ecxt_callback;
     909             : 
     910             :     /* Save the info in appropriate memory context */
     911             :     ecxt_callback = (ExprContext_CB *)
     912     1516006 :         MemoryContextAlloc(econtext->ecxt_per_query_memory,
     913             :                            sizeof(ExprContext_CB));
     914             : 
     915     1516006 :     ecxt_callback->function = function;
     916     1516006 :     ecxt_callback->arg = arg;
     917             : 
     918             :     /* link to front of list for appropriate execution order */
     919     1516006 :     ecxt_callback->next = econtext->ecxt_callbacks;
     920     1516006 :     econtext->ecxt_callbacks = ecxt_callback;
     921     1516006 : }
     922             : 
     923             : /*
     924             :  * Deregister a shutdown callback in an ExprContext.
     925             :  *
     926             :  * Any list entries matching the function and arg will be removed.
     927             :  * This can be used if it's no longer necessary to call the callback.
     928             :  */
     929             : void
     930     1464456 : UnregisterExprContextCallback(ExprContext *econtext,
     931             :                               ExprContextCallbackFunction function,
     932             :                               Datum arg)
     933             : {
     934             :     ExprContext_CB **prev_callback;
     935             :     ExprContext_CB *ecxt_callback;
     936             : 
     937     1464456 :     prev_callback = &econtext->ecxt_callbacks;
     938             : 
     939     3014274 :     while ((ecxt_callback = *prev_callback) != NULL)
     940             :     {
     941     1549818 :         if (ecxt_callback->function == function && ecxt_callback->arg == arg)
     942             :         {
     943     1464456 :             *prev_callback = ecxt_callback->next;
     944     1464456 :             pfree(ecxt_callback);
     945             :         }
     946             :         else
     947       85362 :             prev_callback = &ecxt_callback->next;
     948             :     }
     949     1464456 : }
     950             : 
     951             : /*
     952             :  * Call all the shutdown callbacks registered in an ExprContext.
     953             :  *
     954             :  * The callback list is emptied (important in case this is only a rescan
     955             :  * reset, and not deletion of the ExprContext).
     956             :  *
     957             :  * If isCommit is false, just clean the callback list but don't call 'em.
     958             :  * (See comment for FreeExprContext.)
     959             :  */
     960             : static void
     961    10563856 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
     962             : {
     963             :     ExprContext_CB *ecxt_callback;
     964             :     MemoryContext oldcontext;
     965             : 
     966             :     /* Fast path in normal case where there's nothing to do. */
     967    10563856 :     if (econtext->ecxt_callbacks == NULL)
     968    10514100 :         return;
     969             : 
     970             :     /*
     971             :      * Call the callbacks in econtext's per-tuple context.  This ensures that
     972             :      * any memory they might leak will get cleaned up.
     973             :      */
     974       49756 :     oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
     975             : 
     976             :     /*
     977             :      * Call each callback function in reverse registration order.
     978             :      */
     979      100674 :     while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
     980             :     {
     981       50918 :         econtext->ecxt_callbacks = ecxt_callback->next;
     982       50918 :         if (isCommit)
     983       50918 :             ecxt_callback->function(ecxt_callback->arg);
     984       50918 :         pfree(ecxt_callback);
     985             :     }
     986             : 
     987       49756 :     MemoryContextSwitchTo(oldcontext);
     988             : }
     989             : 
     990             : /*
     991             :  *      GetAttributeByName
     992             :  *      GetAttributeByNum
     993             :  *
     994             :  *      These functions return the value of the requested attribute
     995             :  *      out of the given tuple Datum.
     996             :  *      C functions which take a tuple as an argument are expected
     997             :  *      to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
     998             :  *      Note: these are actually rather slow because they do a typcache
     999             :  *      lookup on each call.
    1000             :  */
    1001             : Datum
    1002          24 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
    1003             : {
    1004             :     AttrNumber  attrno;
    1005             :     Datum       result;
    1006             :     Oid         tupType;
    1007             :     int32       tupTypmod;
    1008             :     TupleDesc   tupDesc;
    1009             :     HeapTupleData tmptup;
    1010             :     int         i;
    1011             : 
    1012          24 :     if (attname == NULL)
    1013           0 :         elog(ERROR, "invalid attribute name");
    1014             : 
    1015          24 :     if (isNull == NULL)
    1016           0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1017             : 
    1018          24 :     if (tuple == NULL)
    1019             :     {
    1020             :         /* Kinda bogus but compatible with old behavior... */
    1021           0 :         *isNull = true;
    1022           0 :         return (Datum) 0;
    1023             :     }
    1024             : 
    1025          24 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1026          24 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1027          24 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1028             : 
    1029          24 :     attrno = InvalidAttrNumber;
    1030          96 :     for (i = 0; i < tupDesc->natts; i++)
    1031             :     {
    1032          96 :         Form_pg_attribute att = TupleDescAttr(tupDesc, i);
    1033             : 
    1034          96 :         if (namestrcmp(&(att->attname), attname) == 0)
    1035             :         {
    1036          24 :             attrno = att->attnum;
    1037          24 :             break;
    1038             :         }
    1039             :     }
    1040             : 
    1041          24 :     if (attrno == InvalidAttrNumber)
    1042           0 :         elog(ERROR, "attribute \"%s\" does not exist", attname);
    1043             : 
    1044             :     /*
    1045             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1046             :      * the fields in the struct just in case user tries to inspect system
    1047             :      * columns.
    1048             :      */
    1049          24 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1050          24 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1051          24 :     tmptup.t_tableOid = InvalidOid;
    1052          24 :     tmptup.t_data = tuple;
    1053             : 
    1054          24 :     result = heap_getattr(&tmptup,
    1055             :                           attrno,
    1056             :                           tupDesc,
    1057             :                           isNull);
    1058             : 
    1059          24 :     ReleaseTupleDesc(tupDesc);
    1060             : 
    1061          24 :     return result;
    1062             : }
    1063             : 
    1064             : Datum
    1065           0 : GetAttributeByNum(HeapTupleHeader tuple,
    1066             :                   AttrNumber attrno,
    1067             :                   bool *isNull)
    1068             : {
    1069             :     Datum       result;
    1070             :     Oid         tupType;
    1071             :     int32       tupTypmod;
    1072             :     TupleDesc   tupDesc;
    1073             :     HeapTupleData tmptup;
    1074             : 
    1075           0 :     if (!AttributeNumberIsValid(attrno))
    1076           0 :         elog(ERROR, "invalid attribute number %d", attrno);
    1077             : 
    1078           0 :     if (isNull == NULL)
    1079           0 :         elog(ERROR, "a NULL isNull pointer was passed");
    1080             : 
    1081           0 :     if (tuple == NULL)
    1082             :     {
    1083             :         /* Kinda bogus but compatible with old behavior... */
    1084           0 :         *isNull = true;
    1085           0 :         return (Datum) 0;
    1086             :     }
    1087             : 
    1088           0 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    1089           0 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    1090           0 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1091             : 
    1092             :     /*
    1093             :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
    1094             :      * the fields in the struct just in case user tries to inspect system
    1095             :      * columns.
    1096             :      */
    1097           0 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    1098           0 :     ItemPointerSetInvalid(&(tmptup.t_self));
    1099           0 :     tmptup.t_tableOid = InvalidOid;
    1100           0 :     tmptup.t_data = tuple;
    1101             : 
    1102           0 :     result = heap_getattr(&tmptup,
    1103             :                           attrno,
    1104             :                           tupDesc,
    1105             :                           isNull);
    1106             : 
    1107           0 :     ReleaseTupleDesc(tupDesc);
    1108             : 
    1109           0 :     return result;
    1110             : }
    1111             : 
    1112             : /*
    1113             :  * Number of items in a tlist (including any resjunk items!)
    1114             :  */
    1115             : int
    1116      810630 : ExecTargetListLength(List *targetlist)
    1117             : {
    1118             :     /* This used to be more complex, but fjoins are dead */
    1119      810630 :     return list_length(targetlist);
    1120             : }
    1121             : 
    1122             : /*
    1123             :  * Number of items in a tlist, not including any resjunk items
    1124             :  */
    1125             : int
    1126       98950 : ExecCleanTargetListLength(List *targetlist)
    1127             : {
    1128       98950 :     int         len = 0;
    1129             :     ListCell   *tl;
    1130             : 
    1131      369198 :     foreach(tl, targetlist)
    1132             :     {
    1133      270248 :         TargetEntry *curTle = lfirst_node(TargetEntry, tl);
    1134             : 
    1135      270248 :         if (!curTle->resjunk)
    1136      233528 :             len++;
    1137             :     }
    1138       98950 :     return len;
    1139             : }
    1140             : 
    1141             : /*
    1142             :  * Return a relInfo's tuple slot for a trigger's OLD tuples.
    1143             :  */
    1144             : TupleTableSlot *
    1145     1017874 : ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
    1146             : {
    1147     1017874 :     if (relInfo->ri_TrigOldSlot == NULL)
    1148             :     {
    1149       20986 :         Relation    rel = relInfo->ri_RelationDesc;
    1150       20986 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1151             : 
    1152       20986 :         relInfo->ri_TrigOldSlot =
    1153       20986 :             ExecInitExtraTupleSlot(estate,
    1154             :                                    RelationGetDescr(rel),
    1155             :                                    table_slot_callbacks(rel));
    1156             : 
    1157       20986 :         MemoryContextSwitchTo(oldcontext);
    1158             :     }
    1159             : 
    1160     1017874 :     return relInfo->ri_TrigOldSlot;
    1161             : }
    1162             : 
    1163             : /*
    1164             :  * Return a relInfo's tuple slot for a trigger's NEW tuples.
    1165             :  */
    1166             : TupleTableSlot *
    1167        1654 : ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
    1168             : {
    1169        1654 :     if (relInfo->ri_TrigNewSlot == NULL)
    1170             :     {
    1171         988 :         Relation    rel = relInfo->ri_RelationDesc;
    1172         988 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1173             : 
    1174         988 :         relInfo->ri_TrigNewSlot =
    1175         988 :             ExecInitExtraTupleSlot(estate,
    1176             :                                    RelationGetDescr(rel),
    1177             :                                    table_slot_callbacks(rel));
    1178             : 
    1179         988 :         MemoryContextSwitchTo(oldcontext);
    1180             :     }
    1181             : 
    1182        1654 :     return relInfo->ri_TrigNewSlot;
    1183             : }
    1184             : 
    1185             : /*
    1186             :  * Return a relInfo's tuple slot for processing returning tuples.
    1187             :  */
    1188             : TupleTableSlot *
    1189         812 : ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
    1190             : {
    1191         812 :     if (relInfo->ri_ReturningSlot == NULL)
    1192             :     {
    1193         330 :         Relation    rel = relInfo->ri_RelationDesc;
    1194         330 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1195             : 
    1196         330 :         relInfo->ri_ReturningSlot =
    1197         330 :             ExecInitExtraTupleSlot(estate,
    1198             :                                    RelationGetDescr(rel),
    1199             :                                    table_slot_callbacks(rel));
    1200             : 
    1201         330 :         MemoryContextSwitchTo(oldcontext);
    1202             :     }
    1203             : 
    1204         812 :     return relInfo->ri_ReturningSlot;
    1205             : }

Generated by: LCOV version 1.13