LCOV - code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 91.2 % 444 405
Test Date: 2026-07-03 19:57:34 Functions: 95.7 % 46 44
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 72.3 % 184 133

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

Generated by: LCOV version 2.0-1