LCOV - differential code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 89.9 % 415 373 19 6 22 11 1 191 52 129 26 192 2 32
Current Date: 2023-04-08 15:15:32 Functions: 93.0 % 43 40 3 36 4 3 37 3
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a