LCOV - code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 88.3 % 557 492
Test Date: 2026-01-26 10:56:24 Functions: 91.1 % 45 41
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 62.8 % 231 145

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

Generated by: LCOV version 2.3.2-1