LCOV - code coverage report
Current view: top level - src/backend/executor - execMain.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 92.6 % 949 879
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 44 44
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 76.6 % 685 525

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * execMain.c
       4                 :             :  *    top level executor interface routines
       5                 :             :  *
       6                 :             :  * INTERFACE ROUTINES
       7                 :             :  *  ExecutorStart()
       8                 :             :  *  ExecutorRun()
       9                 :             :  *  ExecutorFinish()
      10                 :             :  *  ExecutorEnd()
      11                 :             :  *
      12                 :             :  *  These four procedures are the external interface to the executor.
      13                 :             :  *  In each case, the query descriptor is required as an argument.
      14                 :             :  *
      15                 :             :  *  ExecutorStart must be called at the beginning of execution of any
      16                 :             :  *  query plan and ExecutorEnd must always be called at the end of
      17                 :             :  *  execution of a plan (unless it is aborted due to error).
      18                 :             :  *
      19                 :             :  *  ExecutorRun accepts direction and count arguments that specify whether
      20                 :             :  *  the plan is to be executed forwards, backwards, and for how many tuples.
      21                 :             :  *  In some cases ExecutorRun may be called multiple times to process all
      22                 :             :  *  the tuples for a plan.  It is also acceptable to stop short of executing
      23                 :             :  *  the whole plan (but only if it is a SELECT).
      24                 :             :  *
      25                 :             :  *  ExecutorFinish must be called after the final ExecutorRun call and
      26                 :             :  *  before ExecutorEnd.  This can be omitted only in case of EXPLAIN,
      27                 :             :  *  which should also omit ExecutorRun.
      28                 :             :  *
      29                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      30                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      31                 :             :  *
      32                 :             :  *
      33                 :             :  * IDENTIFICATION
      34                 :             :  *    src/backend/executor/execMain.c
      35                 :             :  *
      36                 :             :  *-------------------------------------------------------------------------
      37                 :             :  */
      38                 :             : #include "postgres.h"
      39                 :             : 
      40                 :             : #include "access/sysattr.h"
      41                 :             : #include "access/table.h"
      42                 :             : #include "access/tableam.h"
      43                 :             : #include "access/tupconvert.h"
      44                 :             : #include "access/xact.h"
      45                 :             : #include "catalog/namespace.h"
      46                 :             : #include "catalog/partition.h"
      47                 :             : #include "commands/matview.h"
      48                 :             : #include "commands/trigger.h"
      49                 :             : #include "executor/executor.h"
      50                 :             : #include "executor/execPartition.h"
      51                 :             : #include "executor/instrument.h"
      52                 :             : #include "executor/nodeSubplan.h"
      53                 :             : #include "foreign/fdwapi.h"
      54                 :             : #include "mb/pg_wchar.h"
      55                 :             : #include "miscadmin.h"
      56                 :             : #include "nodes/queryjumble.h"
      57                 :             : #include "parser/parse_relation.h"
      58                 :             : #include "pgstat.h"
      59                 :             : #include "rewrite/rewriteHandler.h"
      60                 :             : #include "tcop/utility.h"
      61                 :             : #include "utils/acl.h"
      62                 :             : #include "utils/backend_status.h"
      63                 :             : #include "utils/lsyscache.h"
      64                 :             : #include "utils/partcache.h"
      65                 :             : #include "utils/rls.h"
      66                 :             : #include "utils/snapmgr.h"
      67                 :             : 
      68                 :             : 
      69                 :             : /* Hooks for plugins to get control in ExecutorStart/Run/Finish/End */
      70                 :             : ExecutorStart_hook_type ExecutorStart_hook = NULL;
      71                 :             : ExecutorRun_hook_type ExecutorRun_hook = NULL;
      72                 :             : ExecutorFinish_hook_type ExecutorFinish_hook = NULL;
      73                 :             : ExecutorEnd_hook_type ExecutorEnd_hook = NULL;
      74                 :             : 
      75                 :             : /* Hook for plugin to get control in ExecCheckPermissions() */
      76                 :             : ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL;
      77                 :             : 
      78                 :             : /* decls for local routines only used within this module */
      79                 :             : static void InitPlan(QueryDesc *queryDesc, int eflags);
      80                 :             : static void CheckValidRowMarkRel(Relation rel, RowMarkType markType);
      81                 :             : static void ExecPostprocessPlan(EState *estate);
      82                 :             : static void ExecEndPlan(PlanState *planstate, EState *estate);
      83                 :             : static void ExecutePlan(QueryDesc *queryDesc,
      84                 :             :                         CmdType operation,
      85                 :             :                         bool sendTuples,
      86                 :             :                         uint64 numberTuples,
      87                 :             :                         ScanDirection direction,
      88                 :             :                         DestReceiver *dest);
      89                 :             : static bool ExecCheckPermissionsModified(Oid relOid, Oid userid,
      90                 :             :                                          Bitmapset *modifiedCols,
      91                 :             :                                          AclMode requiredPerms);
      92                 :             : static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt);
      93                 :             : static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree);
      94                 :             : static void ReportNotNullViolationError(ResultRelInfo *resultRelInfo,
      95                 :             :                                         TupleTableSlot *slot,
      96                 :             :                                         EState *estate, int attnum);
      97                 :             : 
      98                 :             : /* end of local decls */
      99                 :             : 
     100                 :             : 
     101                 :             : /* ----------------------------------------------------------------
     102                 :             :  *      ExecutorStart
     103                 :             :  *
     104                 :             :  *      This routine must be called at the beginning of any execution of any
     105                 :             :  *      query plan
     106                 :             :  *
     107                 :             :  * Takes a QueryDesc previously created by CreateQueryDesc (which is separate
     108                 :             :  * only because some places use QueryDescs for utility commands).  The tupDesc
     109                 :             :  * field of the QueryDesc is filled in to describe the tuples that will be
     110                 :             :  * returned, and the internal fields (estate and planstate) are set up.
     111                 :             :  *
     112                 :             :  * eflags contains flag bits as described in executor.h.
     113                 :             :  *
     114                 :             :  * NB: the CurrentMemoryContext when this is called will become the parent
     115                 :             :  * of the per-query context used for this Executor invocation.
     116                 :             :  *
     117                 :             :  * We provide a function hook variable that lets loadable plugins
     118                 :             :  * get control when ExecutorStart is called.  Such a plugin would
     119                 :             :  * normally call standard_ExecutorStart().
     120                 :             :  *
     121                 :             :  * ----------------------------------------------------------------
     122                 :             :  */
     123                 :             : void
     124                 :      356951 : ExecutorStart(QueryDesc *queryDesc, int eflags)
     125                 :             : {
     126                 :             :     /*
     127                 :             :      * In some cases (e.g. an EXECUTE statement or an execute message with the
     128                 :             :      * extended query protocol) the query_id won't be reported, so do it now.
     129                 :             :      *
     130                 :             :      * Note that it's harmless to report the query_id multiple times, as the
     131                 :             :      * call will be ignored if the top level query_id has already been
     132                 :             :      * reported.
     133                 :             :      */
     134                 :      356951 :     pgstat_report_query_id(queryDesc->plannedstmt->queryId, false);
     135                 :             : 
     136         [ +  + ]:      356951 :     if (ExecutorStart_hook)
     137                 :       60843 :         (*ExecutorStart_hook) (queryDesc, eflags);
     138                 :             :     else
     139                 :      296108 :         standard_ExecutorStart(queryDesc, eflags);
     140                 :      355743 : }
     141                 :             : 
     142                 :             : void
     143                 :      356951 : standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
     144                 :             : {
     145                 :             :     EState     *estate;
     146                 :             :     MemoryContext oldcontext;
     147                 :             : 
     148                 :             :     /* sanity checks: queryDesc must not be started already */
     149                 :             :     Assert(queryDesc != NULL);
     150                 :             :     Assert(queryDesc->estate == NULL);
     151                 :             : 
     152                 :             :     /* caller must ensure the query's snapshot is active */
     153                 :             :     Assert(GetActiveSnapshot() == queryDesc->snapshot);
     154                 :             : 
     155                 :             :     /*
     156                 :             :      * If the transaction is read-only, we need to check if any writes are
     157                 :             :      * planned to non-temporary tables.  EXPLAIN is considered read-only.
     158                 :             :      *
     159                 :             :      * Don't allow writes in parallel mode.  Supporting UPDATE and DELETE
     160                 :             :      * would require (a) storing the combo CID hash in shared memory, rather
     161                 :             :      * than synchronizing it just once at the start of parallelism, and (b) an
     162                 :             :      * alternative to heap_update()'s reliance on xmax for mutual exclusion.
     163                 :             :      * INSERT may have no such troubles, but we forbid it to simplify the
     164                 :             :      * checks.
     165                 :             :      *
     166                 :             :      * We have lower-level defenses in CommandCounterIncrement and elsewhere
     167                 :             :      * against performing unsafe operations in parallel mode, but this gives a
     168                 :             :      * more user-friendly error message.
     169                 :             :      */
     170   [ +  +  +  + ]:      356951 :     if ((XactReadOnly || IsInParallelMode()) &&
     171         [ +  - ]:       33506 :         !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
     172                 :       33506 :         ExecCheckXactReadOnly(queryDesc->plannedstmt);
     173                 :             : 
     174                 :             :     /*
     175                 :             :      * Build EState, switch into per-query memory context for startup.
     176                 :             :      */
     177                 :      356933 :     estate = CreateExecutorState();
     178                 :      356933 :     queryDesc->estate = estate;
     179                 :             : 
     180                 :      356933 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     181                 :             : 
     182                 :             :     /*
     183                 :             :      * Fill in external parameters, if any, from queryDesc; and allocate
     184                 :             :      * workspace for internal parameters
     185                 :             :      */
     186                 :      356933 :     estate->es_param_list_info = queryDesc->params;
     187                 :             : 
     188         [ +  + ]:      356933 :     if (queryDesc->plannedstmt->paramExecTypes != NIL)
     189                 :             :     {
     190                 :             :         int         nParamExec;
     191                 :             : 
     192                 :      118687 :         nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes);
     193                 :      118687 :         estate->es_param_exec_vals = (ParamExecData *)
     194                 :      118687 :             palloc0_array(ParamExecData, nParamExec);
     195                 :             :     }
     196                 :             : 
     197                 :             :     /* We now require all callers to provide sourceText */
     198                 :             :     Assert(queryDesc->sourceText != NULL);
     199                 :      356933 :     estate->es_sourceText = queryDesc->sourceText;
     200                 :             : 
     201                 :             :     /*
     202                 :             :      * Fill in the query environment, if any, from queryDesc.
     203                 :             :      */
     204                 :      356933 :     estate->es_queryEnv = queryDesc->queryEnv;
     205                 :             : 
     206                 :             :     /*
     207                 :             :      * If non-read-only query, set the command ID to mark output tuples with
     208                 :             :      */
     209      [ +  +  - ]:      356933 :     switch (queryDesc->operation)
     210                 :             :     {
     211                 :      283496 :         case CMD_SELECT:
     212                 :             : 
     213                 :             :             /*
     214                 :             :              * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark
     215                 :             :              * tuples
     216                 :             :              */
     217         [ +  + ]:      283496 :             if (queryDesc->plannedstmt->rowMarks != NIL ||
     218         [ +  + ]:      277531 :                 queryDesc->plannedstmt->hasModifyingCTE)
     219                 :        6061 :                 estate->es_output_cid = GetCurrentCommandId(true);
     220                 :             : 
     221                 :             :             /*
     222                 :             :              * A SELECT without modifying CTEs can't possibly queue triggers,
     223                 :             :              * so force skip-triggers mode. This is just a marginal efficiency
     224                 :             :              * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't
     225                 :             :              * all that expensive, but we might as well do it.
     226                 :             :              */
     227         [ +  + ]:      283496 :             if (!queryDesc->plannedstmt->hasModifyingCTE)
     228                 :      283396 :                 eflags |= EXEC_FLAG_SKIP_TRIGGERS;
     229                 :      283496 :             break;
     230                 :             : 
     231                 :       73437 :         case CMD_INSERT:
     232                 :             :         case CMD_DELETE:
     233                 :             :         case CMD_UPDATE:
     234                 :             :         case CMD_MERGE:
     235                 :       73437 :             estate->es_output_cid = GetCurrentCommandId(true);
     236                 :       73437 :             break;
     237                 :             : 
     238                 :           0 :         default:
     239         [ #  # ]:           0 :             elog(ERROR, "unrecognized operation code: %d",
     240                 :             :                  (int) queryDesc->operation);
     241                 :             :             break;
     242                 :             :     }
     243                 :             : 
     244                 :             :     /*
     245                 :             :      * Copy other important information into the EState
     246                 :             :      */
     247                 :      356933 :     estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot);
     248                 :      356933 :     estate->es_crosscheck_snapshot = RegisterSnapshot(queryDesc->crosscheck_snapshot);
     249                 :      356933 :     estate->es_top_eflags = eflags;
     250                 :      356933 :     estate->es_instrument = queryDesc->instrument_options;
     251                 :      356933 :     estate->es_jit_flags = queryDesc->plannedstmt->jitFlags;
     252                 :             : 
     253                 :             :     /*
     254                 :             :      * Set up query-level instrumentation if extensions have requested it via
     255                 :             :      * query_instr_options. Ensure an extension has not allocated query_instr
     256                 :             :      * itself.
     257                 :             :      */
     258                 :             :     Assert(queryDesc->query_instr == NULL);
     259         [ +  + ]:      356933 :     if (queryDesc->query_instr_options)
     260                 :       41700 :         queryDesc->query_instr = InstrAlloc(queryDesc->query_instr_options);
     261                 :             : 
     262                 :             :     /*
     263                 :             :      * Set up an AFTER-trigger statement context, unless told not to, or
     264                 :             :      * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called).
     265                 :             :      */
     266         [ +  + ]:      356933 :     if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY)))
     267                 :       72466 :         AfterTriggerBeginQuery();
     268                 :             : 
     269                 :             :     /*
     270                 :             :      * Initialize the plan state tree
     271                 :             :      */
     272                 :      356933 :     InitPlan(queryDesc, eflags);
     273                 :             : 
     274                 :      355743 :     MemoryContextSwitchTo(oldcontext);
     275                 :      355743 : }
     276                 :             : 
     277                 :             : /* ----------------------------------------------------------------
     278                 :             :  *      ExecutorRun
     279                 :             :  *
     280                 :             :  *      This is the main routine of the executor module. It accepts
     281                 :             :  *      the query descriptor from the traffic cop and executes the
     282                 :             :  *      query plan.
     283                 :             :  *
     284                 :             :  *      ExecutorStart must have been called already.
     285                 :             :  *
     286                 :             :  *      If direction is NoMovementScanDirection then nothing is done
     287                 :             :  *      except to start up/shut down the destination.  Otherwise,
     288                 :             :  *      we retrieve up to 'count' tuples in the specified direction.
     289                 :             :  *
     290                 :             :  *      Note: count = 0 is interpreted as no portal limit, i.e., run to
     291                 :             :  *      completion.  Also note that the count limit is only applied to
     292                 :             :  *      retrieved tuples, not for instance to those inserted/updated/deleted
     293                 :             :  *      by a ModifyTable plan node.
     294                 :             :  *
     295                 :             :  *      There is no return value, but output tuples (if any) are sent to
     296                 :             :  *      the destination receiver specified in the QueryDesc; and the number
     297                 :             :  *      of tuples processed at the top level can be found in
     298                 :             :  *      estate->es_processed.  The total number of tuples processed in all
     299                 :             :  *      the ExecutorRun calls can be found in estate->es_total_processed.
     300                 :             :  *
     301                 :             :  *      We provide a function hook variable that lets loadable plugins
     302                 :             :  *      get control when ExecutorRun is called.  Such a plugin would
     303                 :             :  *      normally call standard_ExecutorRun().
     304                 :             :  *
     305                 :             :  * ----------------------------------------------------------------
     306                 :             :  */
     307                 :             : void
     308                 :      349903 : ExecutorRun(QueryDesc *queryDesc,
     309                 :             :             ScanDirection direction, uint64 count)
     310                 :             : {
     311         [ +  + ]:      349903 :     if (ExecutorRun_hook)
     312                 :       59186 :         (*ExecutorRun_hook) (queryDesc, direction, count);
     313                 :             :     else
     314                 :      290717 :         standard_ExecutorRun(queryDesc, direction, count);
     315                 :      334319 : }
     316                 :             : 
     317                 :             : void
     318                 :      349903 : standard_ExecutorRun(QueryDesc *queryDesc,
     319                 :             :                      ScanDirection direction, uint64 count)
     320                 :             : {
     321                 :             :     EState     *estate;
     322                 :             :     CmdType     operation;
     323                 :             :     DestReceiver *dest;
     324                 :             :     bool        sendTuples;
     325                 :             :     MemoryContext oldcontext;
     326                 :             : 
     327                 :             :     /* sanity checks */
     328                 :             :     Assert(queryDesc != NULL);
     329                 :             : 
     330                 :      349903 :     estate = queryDesc->estate;
     331                 :             : 
     332                 :             :     Assert(estate != NULL);
     333                 :             :     Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
     334                 :             : 
     335                 :             :     /* caller must ensure the query's snapshot is active */
     336                 :             :     Assert(GetActiveSnapshot() == estate->es_snapshot);
     337                 :             : 
     338                 :             :     /*
     339                 :             :      * Switch into per-query memory context
     340                 :             :      */
     341                 :      349903 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     342                 :             : 
     343                 :             :     /* Allow instrumentation of Executor overall runtime */
     344         [ +  + ]:      349903 :     if (queryDesc->query_instr)
     345                 :       41382 :         InstrStart(queryDesc->query_instr);
     346                 :             : 
     347                 :             :     /*
     348                 :             :      * extract information from the query descriptor and the query feature.
     349                 :             :      */
     350                 :      349903 :     operation = queryDesc->operation;
     351                 :      349903 :     dest = queryDesc->dest;
     352                 :             : 
     353                 :             :     /*
     354                 :             :      * startup tuple receiver, if we will be emitting tuples
     355                 :             :      */
     356                 :      349903 :     estate->es_processed = 0;
     357                 :             : 
     358         [ +  + ]:      421965 :     sendTuples = (operation == CMD_SELECT ||
     359         [ +  + ]:       72062 :                   queryDesc->plannedstmt->hasReturning);
     360                 :             : 
     361         [ +  + ]:      349903 :     if (sendTuples)
     362                 :      281109 :         dest->rStartup(dest, operation, queryDesc->tupDesc);
     363                 :             : 
     364                 :             :     /*
     365                 :             :      * Run plan, unless direction is NoMovement.
     366                 :             :      *
     367                 :             :      * Note: pquery.c selects NoMovement if a prior call already reached
     368                 :             :      * end-of-data in the user-specified fetch direction.  This is important
     369                 :             :      * because various parts of the executor can misbehave if called again
     370                 :             :      * after reporting EOF.  For example, heapam.c would actually restart a
     371                 :             :      * heapscan and return all its data afresh.  There is also some doubt
     372                 :             :      * about whether a parallel plan would operate properly if an additional,
     373                 :             :      * necessarily non-parallel execution request occurs after completing a
     374                 :             :      * parallel execution.  (That case should work, but it's untested.)
     375                 :             :      */
     376         [ +  + ]:      349878 :     if (!ScanDirectionIsNoMovement(direction))
     377                 :      349067 :         ExecutePlan(queryDesc,
     378                 :             :                     operation,
     379                 :             :                     sendTuples,
     380                 :             :                     count,
     381                 :             :                     direction,
     382                 :             :                     dest);
     383                 :             : 
     384                 :             :     /*
     385                 :             :      * Update es_total_processed to keep track of the number of tuples
     386                 :             :      * processed across multiple ExecutorRun() calls.
     387                 :             :      */
     388                 :      334319 :     estate->es_total_processed += estate->es_processed;
     389                 :             : 
     390                 :             :     /*
     391                 :             :      * shutdown tuple receiver, if we started it
     392                 :             :      */
     393         [ +  + ]:      334319 :     if (sendTuples)
     394                 :      267701 :         dest->rShutdown(dest);
     395                 :             : 
     396         [ +  + ]:      334319 :     if (queryDesc->query_instr)
     397                 :       39886 :         InstrStop(queryDesc->query_instr);
     398                 :             : 
     399                 :      334319 :     MemoryContextSwitchTo(oldcontext);
     400                 :      334319 : }
     401                 :             : 
     402                 :             : /* ----------------------------------------------------------------
     403                 :             :  *      ExecutorFinish
     404                 :             :  *
     405                 :             :  *      This routine must be called after the last ExecutorRun call.
     406                 :             :  *      It performs cleanup such as firing AFTER triggers.  It is
     407                 :             :  *      separate from ExecutorEnd because EXPLAIN ANALYZE needs to
     408                 :             :  *      include these actions in the total runtime.
     409                 :             :  *
     410                 :             :  *      We provide a function hook variable that lets loadable plugins
     411                 :             :  *      get control when ExecutorFinish is called.  Such a plugin would
     412                 :             :  *      normally call standard_ExecutorFinish().
     413                 :             :  *
     414                 :             :  * ----------------------------------------------------------------
     415                 :             :  */
     416                 :             : void
     417                 :      324651 : ExecutorFinish(QueryDesc *queryDesc)
     418                 :             : {
     419         [ +  + ]:      324651 :     if (ExecutorFinish_hook)
     420                 :       53704 :         (*ExecutorFinish_hook) (queryDesc);
     421                 :             :     else
     422                 :      270947 :         standard_ExecutorFinish(queryDesc);
     423                 :      323842 : }
     424                 :             : 
     425                 :             : void
     426                 :      324651 : standard_ExecutorFinish(QueryDesc *queryDesc)
     427                 :             : {
     428                 :             :     EState     *estate;
     429                 :             :     MemoryContext oldcontext;
     430                 :             : 
     431                 :             :     /* sanity checks */
     432                 :             :     Assert(queryDesc != NULL);
     433                 :             : 
     434                 :      324651 :     estate = queryDesc->estate;
     435                 :             : 
     436                 :             :     Assert(estate != NULL);
     437                 :             :     Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
     438                 :             : 
     439                 :             :     /* This should be run once and only once per Executor instance */
     440                 :             :     Assert(!estate->es_finished);
     441                 :             : 
     442                 :             :     /* Switch into per-query memory context */
     443                 :      324651 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     444                 :             : 
     445                 :             :     /* Allow instrumentation of Executor overall runtime */
     446         [ +  + ]:      324651 :     if (queryDesc->query_instr)
     447                 :       39884 :         InstrStart(queryDesc->query_instr);
     448                 :             : 
     449                 :             :     /* Run ModifyTable nodes to completion */
     450                 :      324651 :     ExecPostprocessPlan(estate);
     451                 :             : 
     452                 :             :     /* Execute queued AFTER triggers, unless told not to */
     453         [ +  + ]:      324651 :     if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
     454                 :       69464 :         AfterTriggerEndQuery(estate);
     455                 :             : 
     456         [ +  + ]:      323842 :     if (queryDesc->query_instr)
     457                 :       39706 :         InstrStop(queryDesc->query_instr);
     458                 :             : 
     459                 :      323842 :     MemoryContextSwitchTo(oldcontext);
     460                 :             : 
     461                 :      323842 :     estate->es_finished = true;
     462                 :      323842 : }
     463                 :             : 
     464                 :             : /* ----------------------------------------------------------------
     465                 :             :  *      ExecutorEnd
     466                 :             :  *
     467                 :             :  *      This routine must be called at the end of execution of any
     468                 :             :  *      query plan
     469                 :             :  *
     470                 :             :  *      We provide a function hook variable that lets loadable plugins
     471                 :             :  *      get control when ExecutorEnd is called.  Such a plugin would
     472                 :             :  *      normally call standard_ExecutorEnd().
     473                 :             :  *
     474                 :             :  * ----------------------------------------------------------------
     475                 :             :  */
     476                 :             : void
     477                 :      337981 : ExecutorEnd(QueryDesc *queryDesc)
     478                 :             : {
     479         [ +  + ]:      337981 :     if (ExecutorEnd_hook)
     480                 :       56629 :         (*ExecutorEnd_hook) (queryDesc);
     481                 :             :     else
     482                 :      281352 :         standard_ExecutorEnd(queryDesc);
     483                 :      337980 : }
     484                 :             : 
     485                 :             : void
     486                 :      337981 : standard_ExecutorEnd(QueryDesc *queryDesc)
     487                 :             : {
     488                 :             :     EState     *estate;
     489                 :             :     MemoryContext oldcontext;
     490                 :             : 
     491                 :             :     /* sanity checks */
     492                 :             :     Assert(queryDesc != NULL);
     493                 :             : 
     494                 :      337981 :     estate = queryDesc->estate;
     495                 :             : 
     496                 :             :     Assert(estate != NULL);
     497                 :             : 
     498         [ +  + ]:      337981 :     if (estate->es_parallel_workers_to_launch > 0)
     499                 :         499 :         pgstat_update_parallel_workers_stats((PgStat_Counter) estate->es_parallel_workers_to_launch,
     500                 :         499 :                                              (PgStat_Counter) estate->es_parallel_workers_launched);
     501                 :             : 
     502                 :             :     /*
     503                 :             :      * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This
     504                 :             :      * Assert is needed because ExecutorFinish is new as of 9.1, and callers
     505                 :             :      * might forget to call it.
     506                 :             :      */
     507                 :             :     Assert(estate->es_finished ||
     508                 :             :            (estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
     509                 :             : 
     510                 :             :     /*
     511                 :             :      * Switch into per-query memory context to run ExecEndPlan
     512                 :             :      */
     513                 :      337981 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     514                 :             : 
     515                 :      337981 :     ExecEndPlan(queryDesc->planstate, estate);
     516                 :             : 
     517                 :             :     /* do away with our snapshots */
     518                 :      337980 :     UnregisterSnapshot(estate->es_snapshot);
     519                 :      337980 :     UnregisterSnapshot(estate->es_crosscheck_snapshot);
     520                 :             : 
     521                 :             :     /*
     522                 :             :      * Must switch out of context before destroying it
     523                 :             :      */
     524                 :      337980 :     MemoryContextSwitchTo(oldcontext);
     525                 :             : 
     526                 :             :     /*
     527                 :             :      * Release EState and per-query memory context.  This should release
     528                 :             :      * everything the executor has allocated.
     529                 :             :      */
     530                 :      337980 :     FreeExecutorState(estate);
     531                 :             : 
     532                 :             :     /* Reset queryDesc fields that no longer point to anything */
     533                 :      337980 :     queryDesc->tupDesc = NULL;
     534                 :      337980 :     queryDesc->estate = NULL;
     535                 :      337980 :     queryDesc->planstate = NULL;
     536                 :      337980 :     queryDesc->query_instr = NULL;
     537                 :      337980 : }
     538                 :             : 
     539                 :             : /* ----------------------------------------------------------------
     540                 :             :  *      ExecutorRewind
     541                 :             :  *
     542                 :             :  *      This routine may be called on an open queryDesc to rewind it
     543                 :             :  *      to the start.
     544                 :             :  * ----------------------------------------------------------------
     545                 :             :  */
     546                 :             : void
     547                 :          67 : ExecutorRewind(QueryDesc *queryDesc)
     548                 :             : {
     549                 :             :     EState     *estate;
     550                 :             :     MemoryContext oldcontext;
     551                 :             : 
     552                 :             :     /* sanity checks */
     553                 :             :     Assert(queryDesc != NULL);
     554                 :             : 
     555                 :          67 :     estate = queryDesc->estate;
     556                 :             : 
     557                 :             :     Assert(estate != NULL);
     558                 :             : 
     559                 :             :     /* It's probably not sensible to rescan updating queries */
     560                 :             :     Assert(queryDesc->operation == CMD_SELECT);
     561                 :             : 
     562                 :             :     /*
     563                 :             :      * Switch into per-query memory context
     564                 :             :      */
     565                 :          67 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     566                 :             : 
     567                 :             :     /*
     568                 :             :      * rescan plan
     569                 :             :      */
     570                 :          67 :     ExecReScan(queryDesc->planstate);
     571                 :             : 
     572                 :          67 :     MemoryContextSwitchTo(oldcontext);
     573                 :          67 : }
     574                 :             : 
     575                 :             : 
     576                 :             : /*
     577                 :             :  * ExecCheckPermissions
     578                 :             :  *      Check access permissions of relations mentioned in a query
     579                 :             :  *
     580                 :             :  * Returns true if permissions are adequate.  Otherwise, throws an appropriate
     581                 :             :  * error if ereport_on_violation is true, or simply returns false otherwise.
     582                 :             :  *
     583                 :             :  * Note that this does NOT address row-level security policies (aka: RLS).  If
     584                 :             :  * rows will be returned to the user as a result of this permission check
     585                 :             :  * passing, then RLS also needs to be consulted (and check_enable_rls()).
     586                 :             :  *
     587                 :             :  * See rewrite/rowsecurity.c.
     588                 :             :  *
     589                 :             :  * NB: rangeTable is no longer used by us, but kept around for the hooks that
     590                 :             :  * might still want to look at the RTEs.
     591                 :             :  */
     592                 :             : bool
     593                 :      363924 : ExecCheckPermissions(List *rangeTable, List *rteperminfos,
     594                 :             :                      bool ereport_on_violation)
     595                 :             : {
     596                 :             :     ListCell   *l;
     597                 :      363924 :     bool        result = true;
     598                 :             : 
     599                 :             : #ifdef USE_ASSERT_CHECKING
     600                 :             :     Bitmapset  *indexset = NULL;
     601                 :             : 
     602                 :             :     /* Check that rteperminfos is consistent with rangeTable */
     603                 :             :     foreach(l, rangeTable)
     604                 :             :     {
     605                 :             :         RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
     606                 :             : 
     607                 :             :         if (rte->perminfoindex != 0)
     608                 :             :         {
     609                 :             :             /* Sanity checks */
     610                 :             : 
     611                 :             :             /*
     612                 :             :              * Only relation RTEs and subquery RTEs that were once relation
     613                 :             :              * RTEs (views, property graphs) have their perminfoindex set.
     614                 :             :              */
     615                 :             :             Assert(rte->rtekind == RTE_RELATION ||
     616                 :             :                    (rte->rtekind == RTE_SUBQUERY &&
     617                 :             :                     (rte->relkind == RELKIND_VIEW || rte->relkind == RELKIND_PROPGRAPH)));
     618                 :             : 
     619                 :             :             (void) getRTEPermissionInfo(rteperminfos, rte);
     620                 :             :             /* Many-to-one mapping not allowed */
     621                 :             :             Assert(!bms_is_member(rte->perminfoindex, indexset));
     622                 :             :             indexset = bms_add_member(indexset, rte->perminfoindex);
     623                 :             :         }
     624                 :             :     }
     625                 :             : 
     626                 :             :     /* All rteperminfos are referenced */
     627                 :             :     Assert(bms_num_members(indexset) == list_length(rteperminfos));
     628                 :             : #endif
     629                 :             : 
     630   [ +  +  +  +  :      733996 :     foreach(l, rteperminfos)
                   +  + ]
     631                 :             :     {
     632                 :      370997 :         RTEPermissionInfo *perminfo = lfirst_node(RTEPermissionInfo, l);
     633                 :             : 
     634                 :             :         Assert(OidIsValid(perminfo->relid));
     635                 :      370997 :         result = ExecCheckOneRelPerms(perminfo);
     636         [ +  + ]:      370997 :         if (!result)
     637                 :             :         {
     638         [ +  + ]:         925 :             if (ereport_on_violation)
     639                 :         917 :                 aclcheck_error(ACLCHECK_NO_PRIV,
     640                 :         917 :                                get_relkind_objtype(get_rel_relkind(perminfo->relid)),
     641                 :         917 :                                get_rel_name(perminfo->relid));
     642                 :           8 :             return false;
     643                 :             :         }
     644                 :             :     }
     645                 :             : 
     646         [ +  + ]:      362999 :     if (ExecutorCheckPerms_hook)
     647                 :           6 :         result = (*ExecutorCheckPerms_hook) (rangeTable, rteperminfos,
     648                 :             :                                              ereport_on_violation);
     649                 :      362999 :     return result;
     650                 :             : }
     651                 :             : 
     652                 :             : /*
     653                 :             :  * ExecCheckOneRelPerms
     654                 :             :  *      Check access permissions for a single relation.
     655                 :             :  */
     656                 :             : bool
     657                 :      387377 : ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
     658                 :             : {
     659                 :             :     AclMode     requiredPerms;
     660                 :             :     AclMode     relPerms;
     661                 :             :     AclMode     remainingPerms;
     662                 :             :     Oid         userid;
     663                 :      387377 :     Oid         relOid = perminfo->relid;
     664                 :             : 
     665                 :      387377 :     requiredPerms = perminfo->requiredPerms;
     666                 :             :     Assert(requiredPerms != 0);
     667                 :             : 
     668                 :             :     /*
     669                 :             :      * userid to check as: current user unless we have a setuid indication.
     670                 :             :      *
     671                 :             :      * Note: GetUserId() is presently fast enough that there's no harm in
     672                 :             :      * calling it separately for each relation.  If that stops being true, we
     673                 :             :      * could call it once in ExecCheckPermissions and pass the userid down
     674                 :             :      * from there.  But for now, no need for the extra clutter.
     675                 :             :      */
     676                 :      774754 :     userid = OidIsValid(perminfo->checkAsUser) ?
     677         [ +  + ]:      387377 :         perminfo->checkAsUser : GetUserId();
     678                 :             : 
     679                 :             :     /*
     680                 :             :      * We must have *all* the requiredPerms bits, but some of the bits can be
     681                 :             :      * satisfied from column-level rather than relation-level permissions.
     682                 :             :      * First, remove any bits that are satisfied by relation permissions.
     683                 :             :      */
     684                 :      387377 :     relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL);
     685                 :      387377 :     remainingPerms = requiredPerms & ~relPerms;
     686         [ +  + ]:      387377 :     if (remainingPerms != 0)
     687                 :             :     {
     688                 :        2063 :         int         col = -1;
     689                 :             : 
     690                 :             :         /*
     691                 :             :          * If we lack any permissions that exist only as relation permissions,
     692                 :             :          * we can fail straight away.
     693                 :             :          */
     694         [ +  + ]:        2063 :         if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE))
     695                 :         104 :             return false;
     696                 :             : 
     697                 :             :         /*
     698                 :             :          * Check to see if we have the needed privileges at column level.
     699                 :             :          *
     700                 :             :          * Note: failures just report a table-level error; it would be nicer
     701                 :             :          * to report a column-level error if we have some but not all of the
     702                 :             :          * column privileges.
     703                 :             :          */
     704         [ +  + ]:        1959 :         if (remainingPerms & ACL_SELECT)
     705                 :             :         {
     706                 :             :             /*
     707                 :             :              * When the query doesn't explicitly reference any columns (for
     708                 :             :              * example, SELECT COUNT(*) FROM table), allow the query if we
     709                 :             :              * have SELECT on any column of the rel, as per SQL spec.
     710                 :             :              */
     711         [ +  + ]:        1115 :             if (bms_is_empty(perminfo->selectedCols))
     712                 :             :             {
     713         [ +  + ]:          64 :                 if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
     714                 :             :                                               ACLMASK_ANY) != ACLCHECK_OK)
     715                 :          24 :                     return false;
     716                 :             :             }
     717                 :             : 
     718         [ +  + ]:        1786 :             while ((col = bms_next_member(perminfo->selectedCols, col)) >= 0)
     719                 :             :             {
     720                 :             :                 /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
     721                 :        1378 :                 AttrNumber  attno = col + FirstLowInvalidHeapAttributeNumber;
     722                 :             : 
     723         [ +  + ]:        1378 :                 if (attno == InvalidAttrNumber)
     724                 :             :                 {
     725                 :             :                     /* Whole-row reference, must have priv on all cols */
     726         [ +  + ]:          44 :                     if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
     727                 :             :                                                   ACLMASK_ALL) != ACLCHECK_OK)
     728                 :          28 :                         return false;
     729                 :             :                 }
     730                 :             :                 else
     731                 :             :                 {
     732         [ +  + ]:        1334 :                     if (pg_attribute_aclcheck(relOid, attno, userid,
     733                 :             :                                               ACL_SELECT) != ACLCHECK_OK)
     734                 :         655 :                         return false;
     735                 :             :                 }
     736                 :             :             }
     737                 :             :         }
     738                 :             : 
     739                 :             :         /*
     740                 :             :          * Basically the same for the mod columns, for both INSERT and UPDATE
     741                 :             :          * privilege as specified by remainingPerms.
     742                 :             :          */
     743         [ +  + ]:        1252 :         if (remainingPerms & ACL_INSERT &&
     744         [ +  + ]:         220 :             !ExecCheckPermissionsModified(relOid,
     745                 :             :                                           userid,
     746                 :             :                                           perminfo->insertedCols,
     747                 :             :                                           ACL_INSERT))
     748                 :         116 :             return false;
     749                 :             : 
     750         [ +  + ]:        1136 :         if (remainingPerms & ACL_UPDATE &&
     751         [ +  + ]:         829 :             !ExecCheckPermissionsModified(relOid,
     752                 :             :                                           userid,
     753                 :             :                                           perminfo->updatedCols,
     754                 :             :                                           ACL_UPDATE))
     755                 :         264 :             return false;
     756                 :             :     }
     757                 :      386186 :     return true;
     758                 :             : }
     759                 :             : 
     760                 :             : /*
     761                 :             :  * ExecCheckPermissionsModified
     762                 :             :  *      Check INSERT or UPDATE access permissions for a single relation (these
     763                 :             :  *      are processed uniformly).
     764                 :             :  */
     765                 :             : static bool
     766                 :        1049 : ExecCheckPermissionsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols,
     767                 :             :                              AclMode requiredPerms)
     768                 :             : {
     769                 :        1049 :     int         col = -1;
     770                 :             : 
     771                 :             :     /*
     772                 :             :      * When the query doesn't explicitly update any columns, allow the query
     773                 :             :      * if we have permission on any column of the rel.  This is to handle
     774                 :             :      * SELECT FOR UPDATE as well as possible corner cases in UPDATE.
     775                 :             :      */
     776         [ +  + ]:        1049 :     if (bms_is_empty(modifiedCols))
     777                 :             :     {
     778         [ +  + ]:          49 :         if (pg_attribute_aclcheck_all(relOid, userid, requiredPerms,
     779                 :             :                                       ACLMASK_ANY) != ACLCHECK_OK)
     780                 :          36 :             return false;
     781                 :             :     }
     782                 :             : 
     783         [ +  + ]:        1784 :     while ((col = bms_next_member(modifiedCols, col)) >= 0)
     784                 :             :     {
     785                 :             :         /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
     786                 :        1115 :         AttrNumber  attno = col + FirstLowInvalidHeapAttributeNumber;
     787                 :             : 
     788         [ -  + ]:        1115 :         if (attno == InvalidAttrNumber)
     789                 :             :         {
     790                 :             :             /* whole-row reference can't happen here */
     791         [ #  # ]:           0 :             elog(ERROR, "whole-row update is not implemented");
     792                 :             :         }
     793                 :             :         else
     794                 :             :         {
     795         [ +  + ]:        1115 :             if (pg_attribute_aclcheck(relOid, attno, userid,
     796                 :             :                                       requiredPerms) != ACLCHECK_OK)
     797                 :         344 :                 return false;
     798                 :             :         }
     799                 :             :     }
     800                 :         669 :     return true;
     801                 :             : }
     802                 :             : 
     803                 :             : /*
     804                 :             :  * Check that the query does not imply any writes to non-temp tables;
     805                 :             :  * unless we're in parallel mode, in which case don't even allow writes
     806                 :             :  * to temp tables.
     807                 :             :  *
     808                 :             :  * Note: in a Hot Standby this would need to reject writes to temp
     809                 :             :  * tables just as we do in parallel mode; but an HS standby can't have created
     810                 :             :  * any temp tables in the first place, so no need to check that.
     811                 :             :  */
     812                 :             : static void
     813                 :       33506 : ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
     814                 :             : {
     815                 :             :     ListCell   *l;
     816                 :             : 
     817                 :             :     /*
     818                 :             :      * Fail if write permissions are requested in parallel mode for table
     819                 :             :      * (temp or non-temp), otherwise fail for any non-temp table.
     820                 :             :      */
     821   [ +  +  +  +  :       95306 :     foreach(l, plannedstmt->permInfos)
                   +  + ]
     822                 :             :     {
     823                 :       61818 :         RTEPermissionInfo *perminfo = lfirst_node(RTEPermissionInfo, l);
     824                 :             : 
     825         [ +  + ]:       61818 :         if ((perminfo->requiredPerms & (~ACL_SELECT)) == 0)
     826                 :       61792 :             continue;
     827                 :             : 
     828         [ +  + ]:          26 :         if (isTempNamespace(get_rel_namespace(perminfo->relid)))
     829                 :           8 :             continue;
     830                 :             : 
     831                 :          18 :         PreventCommandIfReadOnly(CreateCommandName((Node *) plannedstmt));
     832                 :             :     }
     833                 :             : 
     834   [ +  +  -  + ]:       33488 :     if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
     835                 :           8 :         PreventCommandIfParallelMode(CreateCommandName((Node *) plannedstmt));
     836                 :       33488 : }
     837                 :             : 
     838                 :             : 
     839                 :             : /* ----------------------------------------------------------------
     840                 :             :  *      InitPlan
     841                 :             :  *
     842                 :             :  *      Initializes the query plan: open files, allocate storage
     843                 :             :  *      and start up the rule manager
     844                 :             :  * ----------------------------------------------------------------
     845                 :             :  */
     846                 :             : static void
     847                 :      356933 : InitPlan(QueryDesc *queryDesc, int eflags)
     848                 :             : {
     849                 :      356933 :     CmdType     operation = queryDesc->operation;
     850                 :      356933 :     PlannedStmt *plannedstmt = queryDesc->plannedstmt;
     851                 :      356933 :     Plan       *plan = plannedstmt->planTree;
     852                 :      356933 :     List       *rangeTable = plannedstmt->rtable;
     853                 :      356933 :     EState     *estate = queryDesc->estate;
     854                 :             :     PlanState  *planstate;
     855                 :             :     TupleDesc   tupType;
     856                 :             :     ListCell   *l;
     857                 :             :     int         i;
     858                 :             : 
     859                 :             :     /*
     860                 :             :      * Do permissions checks
     861                 :             :      */
     862                 :      356933 :     ExecCheckPermissions(rangeTable, plannedstmt->permInfos, true);
     863                 :             : 
     864                 :             :     /*
     865                 :             :      * initialize the node's execution state
     866                 :             :      */
     867                 :      356072 :     ExecInitRangeTable(estate, rangeTable, plannedstmt->permInfos,
     868                 :      356072 :                        bms_copy(plannedstmt->unprunableRelids));
     869                 :             : 
     870                 :      356072 :     estate->es_plannedstmt = plannedstmt;
     871                 :      356072 :     estate->es_part_prune_infos = plannedstmt->partPruneInfos;
     872                 :             : 
     873                 :             :     /*
     874                 :             :      * Perform runtime "initial" pruning to identify which child subplans,
     875                 :             :      * corresponding to the children of plan nodes that contain
     876                 :             :      * PartitionPruneInfo such as Append, will not be executed. The results,
     877                 :             :      * which are bitmapsets of indexes of the child subplans that will be
     878                 :             :      * executed, are saved in es_part_prune_results.  These results correspond
     879                 :             :      * to each PartitionPruneInfo entry, and the es_part_prune_results list is
     880                 :             :      * parallel to es_part_prune_infos.
     881                 :             :      */
     882                 :      356072 :     ExecDoInitialPruning(estate);
     883                 :             : 
     884                 :             :     /*
     885                 :             :      * Next, build the ExecRowMark array from the PlanRowMark(s), if any.
     886                 :             :      */
     887         [ +  + ]:      356072 :     if (plannedstmt->rowMarks)
     888                 :             :     {
     889                 :        7368 :         estate->es_rowmarks = (ExecRowMark **)
     890                 :        7368 :             palloc0_array(ExecRowMark *, estate->es_range_table_size);
     891   [ +  -  +  +  :       16970 :         foreach(l, plannedstmt->rowMarks)
                   +  + ]
     892                 :             :         {
     893                 :        9610 :             PlanRowMark *rc = (PlanRowMark *) lfirst(l);
     894                 :        9610 :             RangeTblEntry *rte = exec_rt_fetch(rc->rti, estate);
     895                 :             :             Oid         relid;
     896                 :             :             Relation    relation;
     897                 :             :             ExecRowMark *erm;
     898                 :             : 
     899                 :             :             /* ignore "parent" rowmarks; they are irrelevant at runtime */
     900         [ +  + ]:        9610 :             if (rc->isParent)
     901                 :        1278 :                 continue;
     902                 :             : 
     903                 :             :             /*
     904                 :             :              * Also ignore rowmarks belonging to child tables that have been
     905                 :             :              * pruned in ExecDoInitialPruning().
     906                 :             :              */
     907         [ +  + ]:        8332 :             if (rte->rtekind == RTE_RELATION &&
     908         [ +  + ]:        7955 :                 !bms_is_member(rc->rti, estate->es_unpruned_relids))
     909                 :          48 :                 continue;
     910                 :             : 
     911                 :             :             /* get relation's OID (will produce InvalidOid if subquery) */
     912                 :        8284 :             relid = rte->relid;
     913                 :             : 
     914                 :             :             /* open relation, if we need to access it for this mark type */
     915      [ +  +  - ]:        8284 :             switch (rc->markType)
     916                 :             :             {
     917                 :        7797 :                 case ROW_MARK_EXCLUSIVE:
     918                 :             :                 case ROW_MARK_NOKEYEXCLUSIVE:
     919                 :             :                 case ROW_MARK_SHARE:
     920                 :             :                 case ROW_MARK_KEYSHARE:
     921                 :             :                 case ROW_MARK_REFERENCE:
     922                 :        7797 :                     relation = ExecGetRangeTableRelation(estate, rc->rti, false);
     923                 :        7797 :                     break;
     924                 :         487 :                 case ROW_MARK_COPY:
     925                 :             :                     /* no physical table access is required */
     926                 :         487 :                     relation = NULL;
     927                 :         487 :                     break;
     928                 :           0 :                 default:
     929         [ #  # ]:           0 :                     elog(ERROR, "unrecognized markType: %d", rc->markType);
     930                 :             :                     relation = NULL;    /* keep compiler quiet */
     931                 :             :                     break;
     932                 :             :             }
     933                 :             : 
     934                 :             :             /* Check that relation is a legal target for marking */
     935         [ +  + ]:        8284 :             if (relation)
     936                 :        7797 :                 CheckValidRowMarkRel(relation, rc->markType);
     937                 :             : 
     938                 :        8276 :             erm = palloc_object(ExecRowMark);
     939                 :        8276 :             erm->relation = relation;
     940                 :        8276 :             erm->relid = relid;
     941                 :        8276 :             erm->rti = rc->rti;
     942                 :        8276 :             erm->prti = rc->prti;
     943                 :        8276 :             erm->rowmarkId = rc->rowmarkId;
     944                 :        8276 :             erm->markType = rc->markType;
     945                 :        8276 :             erm->strength = rc->strength;
     946                 :        8276 :             erm->waitPolicy = rc->waitPolicy;
     947                 :        8276 :             erm->ermActive = false;
     948                 :        8276 :             ItemPointerSetInvalid(&(erm->curCtid));
     949                 :        8276 :             erm->ermExtra = NULL;
     950                 :             : 
     951                 :             :             Assert(erm->rti > 0 && erm->rti <= estate->es_range_table_size &&
     952                 :             :                    estate->es_rowmarks[erm->rti - 1] == NULL);
     953                 :             : 
     954                 :        8276 :             estate->es_rowmarks[erm->rti - 1] = erm;
     955                 :             :         }
     956                 :             :     }
     957                 :             : 
     958                 :             :     /*
     959                 :             :      * Initialize the executor's tuple table to empty.
     960                 :             :      */
     961                 :      356064 :     estate->es_tupleTable = NIL;
     962                 :             : 
     963                 :             :     /* signal that this EState is not used for EPQ */
     964                 :      356064 :     estate->es_epq_active = NULL;
     965                 :             : 
     966                 :             :     /*
     967                 :             :      * Initialize private state information for each SubPlan.  We must do this
     968                 :             :      * before running ExecInitNode on the main query tree, since
     969                 :             :      * ExecInitSubPlan expects to be able to find these entries.
     970                 :             :      */
     971                 :             :     Assert(estate->es_subplanstates == NIL);
     972                 :      356064 :     i = 1;                      /* subplan indices count from 1 */
     973   [ +  +  +  +  :      384957 :     foreach(l, plannedstmt->subplans)
                   +  + ]
     974                 :             :     {
     975                 :       28893 :         Plan       *subplan = (Plan *) lfirst(l);
     976                 :             :         PlanState  *subplanstate;
     977                 :             :         int         sp_eflags;
     978                 :             : 
     979                 :             :         /*
     980                 :             :          * A subplan will never need to do BACKWARD scan nor MARK/RESTORE. If
     981                 :             :          * it is a parameterless subplan (not initplan), we suggest that it be
     982                 :             :          * prepared to handle REWIND efficiently; otherwise there is no need.
     983                 :             :          */
     984                 :       28893 :         sp_eflags = eflags
     985                 :             :             & ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
     986         [ +  + ]:       28893 :         if (bms_is_member(i, plannedstmt->rewindPlanIDs))
     987                 :          36 :             sp_eflags |= EXEC_FLAG_REWIND;
     988                 :             : 
     989                 :       28893 :         subplanstate = ExecInitNode(subplan, estate, sp_eflags);
     990                 :             : 
     991                 :       28893 :         estate->es_subplanstates = lappend(estate->es_subplanstates,
     992                 :             :                                            subplanstate);
     993                 :             : 
     994                 :       28893 :         i++;
     995                 :             :     }
     996                 :             : 
     997                 :             :     /*
     998                 :             :      * Initialize the private state information for all the nodes in the query
     999                 :             :      * tree.  This opens files, allocates storage and leaves us ready to start
    1000                 :             :      * processing tuples.
    1001                 :             :      */
    1002                 :      356064 :     planstate = ExecInitNode(plan, estate, eflags);
    1003                 :             : 
    1004                 :             :     /*
    1005                 :             :      * Get the tuple descriptor describing the type of tuples to return.
    1006                 :             :      */
    1007                 :      355743 :     tupType = ExecGetResultType(planstate);
    1008                 :             : 
    1009                 :             :     /*
    1010                 :             :      * Initialize the junk filter if needed.  SELECT queries need a filter if
    1011                 :             :      * there are any junk attrs in the top-level tlist.
    1012                 :             :      */
    1013         [ +  + ]:      355743 :     if (operation == CMD_SELECT)
    1014                 :             :     {
    1015                 :      283030 :         bool        junk_filter_needed = false;
    1016                 :             :         ListCell   *tlist;
    1017                 :             : 
    1018   [ +  +  +  +  :     1038912 :         foreach(tlist, plan->targetlist)
                   +  + ]
    1019                 :             :         {
    1020                 :      770713 :             TargetEntry *tle = (TargetEntry *) lfirst(tlist);
    1021                 :             : 
    1022         [ +  + ]:      770713 :             if (tle->resjunk)
    1023                 :             :             {
    1024                 :       14831 :                 junk_filter_needed = true;
    1025                 :       14831 :                 break;
    1026                 :             :             }
    1027                 :             :         }
    1028                 :             : 
    1029         [ +  + ]:      283030 :         if (junk_filter_needed)
    1030                 :             :         {
    1031                 :             :             JunkFilter *j;
    1032                 :             :             TupleTableSlot *slot;
    1033                 :             : 
    1034                 :       14831 :             slot = ExecInitExtraTupleSlot(estate, NULL, &TTSOpsVirtual);
    1035                 :       14831 :             j = ExecInitJunkFilter(planstate->plan->targetlist,
    1036                 :             :                                    slot);
    1037                 :       14831 :             estate->es_junkFilter = j;
    1038                 :             : 
    1039                 :             :             /* Want to return the cleaned tuple type */
    1040                 :       14831 :             tupType = j->jf_cleanTupType;
    1041                 :             :         }
    1042                 :             :     }
    1043                 :             : 
    1044                 :      355743 :     queryDesc->tupDesc = tupType;
    1045                 :      355743 :     queryDesc->planstate = planstate;
    1046                 :      355743 : }
    1047                 :             : 
    1048                 :             : /*
    1049                 :             :  * Check that a proposed result relation is a legal target for the operation
    1050                 :             :  *
    1051                 :             :  * Generally the parser and/or planner should have noticed any such mistake
    1052                 :             :  * already, but let's make sure.
    1053                 :             :  *
    1054                 :             :  * For INSERT ON CONFLICT, the result relation is required to support the
    1055                 :             :  * onConflictAction, regardless of whether a conflict actually occurs.
    1056                 :             :  *
    1057                 :             :  * For MERGE, mergeActions is the list of actions that may be performed.  The
    1058                 :             :  * result relation is required to support every action, regardless of whether
    1059                 :             :  * or not they are all executed.
    1060                 :             :  *
    1061                 :             :  * Note: when changing this function, you probably also need to look at
    1062                 :             :  * CheckValidRowMarkRel.
    1063                 :             :  */
    1064                 :             : void
    1065                 :       81159 : CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation,
    1066                 :             :                     OnConflictAction onConflictAction, List *mergeActions,
    1067                 :             :                     ModifyTable *mtnode)
    1068                 :             : {
    1069                 :       81159 :     Relation    resultRel = resultRelInfo->ri_RelationDesc;
    1070                 :             :     FdwRoutine *fdwroutine;
    1071                 :             : 
    1072                 :             :     /* Expect a fully-formed ResultRelInfo from InitResultRelInfo(). */
    1073                 :             :     Assert(resultRelInfo->ri_needLockTagTuple ==
    1074                 :             :            IsInplaceUpdateRelation(resultRel));
    1075                 :             : 
    1076   [ +  -  -  +  :       81159 :     switch (resultRel->rd_rel->relkind)
             +  +  -  - ]
    1077                 :             :     {
    1078                 :       80453 :         case RELKIND_RELATION:
    1079                 :             :         case RELKIND_PARTITIONED_TABLE:
    1080                 :             : 
    1081                 :             :             /*
    1082                 :             :              * For MERGE, check that the target relation supports each action.
    1083                 :             :              * For other operations, just check the operation itself.
    1084                 :             :              */
    1085         [ +  + ]:       80453 :             if (operation == CMD_MERGE)
    1086   [ +  -  +  +  :        4349 :                 foreach_node(MergeAction, action, mergeActions)
                   +  + ]
    1087                 :        2029 :                     CheckCmdReplicaIdentity(resultRel, action->commandType);
    1088                 :             :             else
    1089                 :       79285 :                 CheckCmdReplicaIdentity(resultRel, operation);
    1090                 :             : 
    1091                 :             :             /*
    1092                 :             :              * For INSERT ON CONFLICT DO UPDATE, additionally check that the
    1093                 :             :              * target relation supports UPDATE.
    1094                 :             :              */
    1095         [ +  + ]:       80238 :             if (onConflictAction == ONCONFLICT_UPDATE)
    1096                 :         801 :                 CheckCmdReplicaIdentity(resultRel, CMD_UPDATE);
    1097                 :       80230 :             break;
    1098                 :           0 :         case RELKIND_SEQUENCE:
    1099         [ #  # ]:           0 :             ereport(ERROR,
    1100                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1101                 :             :                      errmsg("cannot change sequence \"%s\"",
    1102                 :             :                             RelationGetRelationName(resultRel))));
    1103                 :             :             break;
    1104                 :           0 :         case RELKIND_TOASTVALUE:
    1105         [ #  # ]:           0 :             ereport(ERROR,
    1106                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1107                 :             :                      errmsg("cannot change TOAST relation \"%s\"",
    1108                 :             :                             RelationGetRelationName(resultRel))));
    1109                 :             :             break;
    1110                 :         277 :         case RELKIND_VIEW:
    1111                 :             : 
    1112                 :             :             /*
    1113                 :             :              * Okay only if there's a suitable INSTEAD OF trigger.  Otherwise,
    1114                 :             :              * complain, but omit errdetail because we haven't got the
    1115                 :             :              * information handy (and given that it really shouldn't happen,
    1116                 :             :              * it's not worth great exertion to get).
    1117                 :             :              */
    1118         [ -  + ]:         277 :             if (!view_has_instead_trigger(resultRel, operation, mergeActions))
    1119                 :           0 :                 error_view_not_updatable(resultRel, operation, mergeActions,
    1120                 :             :                                          NULL);
    1121                 :         277 :             break;
    1122                 :          74 :         case RELKIND_MATVIEW:
    1123         [ -  + ]:          74 :             if (!MatViewIncrementalMaintenanceIsEnabled())
    1124         [ #  # ]:           0 :                 ereport(ERROR,
    1125                 :             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1126                 :             :                          errmsg("cannot change materialized view \"%s\"",
    1127                 :             :                                 RelationGetRelationName(resultRel))));
    1128                 :          74 :             break;
    1129                 :         355 :         case RELKIND_FOREIGN_TABLE:
    1130                 :             :             /* We don't support FOR PORTION OF FDW queries. */
    1131   [ +  +  +  + ]:         355 :             if (mtnode && mtnode->forPortionOf)
    1132         [ +  - ]:           4 :                 ereport(ERROR,
    1133                 :             :                         errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1134                 :             :                         errmsg("foreign tables don't support FOR PORTION OF"),
    1135                 :             :                         errdetail("\"%s\" is a foreign table.",
    1136                 :             :                                   RelationGetRelationName(resultRel)));
    1137                 :             : 
    1138                 :             :             /* Okay only if the FDW supports it */
    1139                 :         351 :             fdwroutine = resultRelInfo->ri_FdwRoutine;
    1140   [ +  +  +  - ]:         351 :             switch (operation)
    1141                 :             :             {
    1142                 :         157 :                 case CMD_INSERT:
    1143         [ +  + ]:         157 :                     if (fdwroutine->ExecForeignInsert == NULL)
    1144         [ +  - ]:           5 :                         ereport(ERROR,
    1145                 :             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1146                 :             :                                  errmsg("cannot insert into foreign table \"%s\"",
    1147                 :             :                                         RelationGetRelationName(resultRel))));
    1148         [ +  - ]:         152 :                     if (fdwroutine->IsForeignRelUpdatable != NULL &&
    1149         [ -  + ]:         152 :                         (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
    1150         [ #  # ]:           0 :                         ereport(ERROR,
    1151                 :             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1152                 :             :                                  errmsg("foreign table \"%s\" does not allow inserts",
    1153                 :             :                                         RelationGetRelationName(resultRel))));
    1154                 :         152 :                     break;
    1155                 :         111 :                 case CMD_UPDATE:
    1156         [ +  + ]:         111 :                     if (fdwroutine->ExecForeignUpdate == NULL)
    1157         [ +  - ]:           2 :                         ereport(ERROR,
    1158                 :             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1159                 :             :                                  errmsg("cannot update foreign table \"%s\"",
    1160                 :             :                                         RelationGetRelationName(resultRel))));
    1161         [ +  - ]:         109 :                     if (fdwroutine->IsForeignRelUpdatable != NULL &&
    1162         [ -  + ]:         109 :                         (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
    1163         [ #  # ]:           0 :                         ereport(ERROR,
    1164                 :             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1165                 :             :                                  errmsg("foreign table \"%s\" does not allow updates",
    1166                 :             :                                         RelationGetRelationName(resultRel))));
    1167                 :         109 :                     break;
    1168                 :          83 :                 case CMD_DELETE:
    1169         [ +  + ]:          83 :                     if (fdwroutine->ExecForeignDelete == NULL)
    1170         [ +  - ]:           2 :                         ereport(ERROR,
    1171                 :             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1172                 :             :                                  errmsg("cannot delete from foreign table \"%s\"",
    1173                 :             :                                         RelationGetRelationName(resultRel))));
    1174         [ +  - ]:          81 :                     if (fdwroutine->IsForeignRelUpdatable != NULL &&
    1175         [ -  + ]:          81 :                         (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
    1176         [ #  # ]:           0 :                         ereport(ERROR,
    1177                 :             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1178                 :             :                                  errmsg("foreign table \"%s\" does not allow deletes",
    1179                 :             :                                         RelationGetRelationName(resultRel))));
    1180                 :          81 :                     break;
    1181                 :           0 :                 default:
    1182         [ #  # ]:           0 :                     elog(ERROR, "unrecognized CmdType: %d", (int) operation);
    1183                 :             :                     break;
    1184                 :             :             }
    1185                 :         342 :             break;
    1186                 :           0 :         case RELKIND_PROPGRAPH:
    1187         [ #  # ]:           0 :             ereport(ERROR,
    1188                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1189                 :             :                      errmsg("cannot change property graph \"%s\"",
    1190                 :             :                             RelationGetRelationName(resultRel))));
    1191                 :             :             break;
    1192                 :           0 :         default:
    1193         [ #  # ]:           0 :             ereport(ERROR,
    1194                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1195                 :             :                      errmsg("cannot change relation \"%s\"",
    1196                 :             :                             RelationGetRelationName(resultRel))));
    1197                 :             :             break;
    1198                 :             :     }
    1199                 :             : 
    1200                 :             :     /*
    1201                 :             :      * Conflict log tables are managed by the system to record logical
    1202                 :             :      * replication conflicts.  We allow DELETE and TRUNCATE to permit users to
    1203                 :             :      * manually prune these logs, but manual data insertion or modification
    1204                 :             :      * (INSERT, UPDATE, MERGE) is prohibited to maintain the integrity of the
    1205                 :             :      * system-generated logs.
    1206                 :             :      *
    1207                 :             :      * Since TRUNCATE is handled as a separate utility command, we only need
    1208                 :             :      * to explicitly permit CMD_DELETE here.
    1209                 :             :      */
    1210   [ +  +  +  + ]:       80923 :     if (IsConflictLogTableNamespace(RelationGetNamespace(resultRel)) &&
    1211                 :             :         operation != CMD_DELETE)
    1212         [ +  - ]:           8 :         ereport(ERROR,
    1213                 :             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1214                 :             :                  errmsg("cannot modify or insert data into conflict log table \"%s\"",
    1215                 :             :                         RelationGetRelationName(resultRel)),
    1216                 :             :                  errdetail("Conflict log tables are system-managed and only support cleanup using DELETE or TRUNCATE.")));
    1217                 :       80915 : }
    1218                 :             : 
    1219                 :             : /*
    1220                 :             :  * Check that a proposed rowmark target relation is a legal target
    1221                 :             :  *
    1222                 :             :  * In most cases parser and/or planner should have noticed this already, but
    1223                 :             :  * they don't cover all cases.
    1224                 :             :  */
    1225                 :             : static void
    1226                 :        7797 : CheckValidRowMarkRel(Relation rel, RowMarkType markType)
    1227                 :             : {
    1228                 :             :     FdwRoutine *fdwroutine;
    1229                 :             : 
    1230   [ +  -  -  -  :        7797 :     switch (rel->rd_rel->relkind)
             +  -  -  - ]
    1231                 :             :     {
    1232                 :        7789 :         case RELKIND_RELATION:
    1233                 :             :         case RELKIND_PARTITIONED_TABLE:
    1234                 :             :             /* OK */
    1235                 :        7789 :             break;
    1236                 :           0 :         case RELKIND_SEQUENCE:
    1237                 :             :             /* Must disallow this because we don't vacuum sequences */
    1238         [ #  # ]:           0 :             ereport(ERROR,
    1239                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1240                 :             :                      errmsg("cannot lock rows in sequence \"%s\"",
    1241                 :             :                             RelationGetRelationName(rel))));
    1242                 :             :             break;
    1243                 :           0 :         case RELKIND_TOASTVALUE:
    1244                 :             :             /* We could allow this, but there seems no good reason to */
    1245         [ #  # ]:           0 :             ereport(ERROR,
    1246                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1247                 :             :                      errmsg("cannot lock rows in TOAST relation \"%s\"",
    1248                 :             :                             RelationGetRelationName(rel))));
    1249                 :             :             break;
    1250                 :           0 :         case RELKIND_VIEW:
    1251                 :             :             /* Should not get here; planner should have expanded the view */
    1252         [ #  # ]:           0 :             ereport(ERROR,
    1253                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1254                 :             :                      errmsg("cannot lock rows in view \"%s\"",
    1255                 :             :                             RelationGetRelationName(rel))));
    1256                 :             :             break;
    1257                 :           8 :         case RELKIND_MATVIEW:
    1258                 :             :             /* Allow referencing a matview, but not actual locking clauses */
    1259         [ +  + ]:           8 :             if (markType != ROW_MARK_REFERENCE)
    1260         [ +  - ]:           4 :                 ereport(ERROR,
    1261                 :             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1262                 :             :                          errmsg("cannot lock rows in materialized view \"%s\"",
    1263                 :             :                                 RelationGetRelationName(rel))));
    1264                 :           4 :             break;
    1265                 :           0 :         case RELKIND_FOREIGN_TABLE:
    1266                 :             :             /* Okay only if the FDW supports it */
    1267                 :           0 :             fdwroutine = GetFdwRoutineForRelation(rel, false);
    1268         [ #  # ]:           0 :             if (fdwroutine->RefetchForeignRow == NULL)
    1269         [ #  # ]:           0 :                 ereport(ERROR,
    1270                 :             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1271                 :             :                          errmsg("cannot lock rows in foreign table \"%s\"",
    1272                 :             :                                 RelationGetRelationName(rel))));
    1273                 :           0 :             break;
    1274                 :           0 :         case RELKIND_PROPGRAPH:
    1275                 :             :             /* Should not get here; rewriter should have expanded the graph */
    1276         [ #  # ]:           0 :             ereport(ERROR,
    1277                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1278                 :             :                      errmsg_internal("cannot lock rows in property graph \"%s\"",
    1279                 :             :                                      RelationGetRelationName(rel))));
    1280                 :             :             break;
    1281                 :           0 :         default:
    1282         [ #  # ]:           0 :             ereport(ERROR,
    1283                 :             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1284                 :             :                      errmsg("cannot lock rows in relation \"%s\"",
    1285                 :             :                             RelationGetRelationName(rel))));
    1286                 :             :             break;
    1287                 :             :     }
    1288                 :             : 
    1289                 :             :     /*
    1290                 :             :      * Conflict log tables are managed by the system to record logical
    1291                 :             :      * replication conflicts.
    1292                 :             :      */
    1293         [ +  + ]:        7793 :     if (IsConflictLogTableNamespace(RelationGetNamespace(rel)))
    1294         [ +  - ]:           4 :         ereport(ERROR,
    1295                 :             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1296                 :             :                  errmsg("cannot lock rows in the conflict log table \"%s\"",
    1297                 :             :                         RelationGetRelationName(rel))));
    1298                 :        7789 : }
    1299                 :             : 
    1300                 :             : /*
    1301                 :             :  * Initialize ResultRelInfo data for one result relation
    1302                 :             :  *
    1303                 :             :  * Caution: before Postgres 9.1, this function included the relkind checking
    1304                 :             :  * that's now in CheckValidResultRel, and it also did ExecOpenIndices if
    1305                 :             :  * appropriate.  Be sure callers cover those needs.
    1306                 :             :  */
    1307                 :             : void
    1308                 :      256170 : InitResultRelInfo(ResultRelInfo *resultRelInfo,
    1309                 :             :                   Relation resultRelationDesc,
    1310                 :             :                   Index resultRelationIndex,
    1311                 :             :                   ResultRelInfo *partition_root_rri,
    1312                 :             :                   int instrument_options)
    1313                 :             : {
    1314   [ +  -  +  -  :    13320840 :     MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
          +  -  +  -  +  
                      + ]
    1315                 :      256170 :     resultRelInfo->type = T_ResultRelInfo;
    1316                 :      256170 :     resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
    1317                 :      256170 :     resultRelInfo->ri_RelationDesc = resultRelationDesc;
    1318                 :      256170 :     resultRelInfo->ri_NumIndices = 0;
    1319                 :      256170 :     resultRelInfo->ri_IndexRelationDescs = NULL;
    1320                 :      256170 :     resultRelInfo->ri_IndexRelationInfo = NULL;
    1321                 :      256170 :     resultRelInfo->ri_needLockTagTuple =
    1322                 :      256170 :         IsInplaceUpdateRelation(resultRelationDesc);
    1323                 :             :     /* make a copy so as not to depend on relcache info not changing... */
    1324                 :      256170 :     resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
    1325         [ +  + ]:      256170 :     if (resultRelInfo->ri_TrigDesc)
    1326                 :             :     {
    1327                 :       12825 :         int         n = resultRelInfo->ri_TrigDesc->numtriggers;
    1328                 :             : 
    1329                 :       12825 :         resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
    1330                 :       12825 :             palloc0_array(FmgrInfo, n);
    1331                 :       12825 :         resultRelInfo->ri_TrigWhenExprs = (ExprState **)
    1332                 :       12825 :             palloc0_array(ExprState *, n);
    1333         [ -  + ]:       12825 :         if (instrument_options)
    1334                 :           0 :             resultRelInfo->ri_TrigInstrument = InstrAllocTrigger(n, instrument_options);
    1335                 :             :     }
    1336                 :             :     else
    1337                 :             :     {
    1338                 :      243345 :         resultRelInfo->ri_TrigFunctions = NULL;
    1339                 :      243345 :         resultRelInfo->ri_TrigWhenExprs = NULL;
    1340                 :      243345 :         resultRelInfo->ri_TrigInstrument = NULL;
    1341                 :             :     }
    1342         [ +  + ]:      256170 :     if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
    1343                 :         368 :         resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
    1344                 :             :     else
    1345                 :      255802 :         resultRelInfo->ri_FdwRoutine = NULL;
    1346                 :             : 
    1347                 :             :     /* The following fields are set later if needed */
    1348                 :      256170 :     resultRelInfo->ri_RowIdAttNo = 0;
    1349                 :      256170 :     resultRelInfo->ri_extraUpdatedCols = NULL;
    1350                 :      256170 :     resultRelInfo->ri_projectNew = NULL;
    1351                 :      256170 :     resultRelInfo->ri_newTupleSlot = NULL;
    1352                 :      256170 :     resultRelInfo->ri_oldTupleSlot = NULL;
    1353                 :      256170 :     resultRelInfo->ri_projectNewInfoValid = false;
    1354                 :      256170 :     resultRelInfo->ri_FdwState = NULL;
    1355                 :      256170 :     resultRelInfo->ri_usesFdwDirectModify = false;
    1356                 :      256170 :     resultRelInfo->ri_CheckConstraintExprs = NULL;
    1357                 :      256170 :     resultRelInfo->ri_GenVirtualNotNullConstraintExprs = NULL;
    1358                 :      256170 :     resultRelInfo->ri_GeneratedExprsI = NULL;
    1359                 :      256170 :     resultRelInfo->ri_GeneratedExprsU = NULL;
    1360                 :      256170 :     resultRelInfo->ri_projectReturning = NULL;
    1361                 :      256170 :     resultRelInfo->ri_onConflictArbiterIndexes = NIL;
    1362                 :      256170 :     resultRelInfo->ri_onConflict = NULL;
    1363                 :      256170 :     resultRelInfo->ri_forPortionOf = NULL;
    1364                 :      256170 :     resultRelInfo->ri_ReturningSlot = NULL;
    1365                 :      256170 :     resultRelInfo->ri_TrigOldSlot = NULL;
    1366                 :      256170 :     resultRelInfo->ri_TrigNewSlot = NULL;
    1367                 :      256170 :     resultRelInfo->ri_AllNullSlot = NULL;
    1368                 :      256170 :     resultRelInfo->ri_MergeActions[MERGE_WHEN_MATCHED] = NIL;
    1369                 :      256170 :     resultRelInfo->ri_MergeActions[MERGE_WHEN_NOT_MATCHED_BY_SOURCE] = NIL;
    1370                 :      256170 :     resultRelInfo->ri_MergeActions[MERGE_WHEN_NOT_MATCHED_BY_TARGET] = NIL;
    1371                 :      256170 :     resultRelInfo->ri_MergeJoinCondition = NULL;
    1372                 :             : 
    1373                 :             :     /*
    1374                 :             :      * Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
    1375                 :             :      * non-NULL partition_root_rri.  For child relations that are part of the
    1376                 :             :      * initial query rather than being dynamically added by tuple routing,
    1377                 :             :      * this field is filled in ExecInitModifyTable().
    1378                 :             :      */
    1379                 :      256170 :     resultRelInfo->ri_RootResultRelInfo = partition_root_rri;
    1380                 :             :     /* Set by ExecGetRootToChildMap */
    1381                 :      256170 :     resultRelInfo->ri_RootToChildMap = NULL;
    1382                 :      256170 :     resultRelInfo->ri_RootToChildMapValid = false;
    1383                 :             :     /* Set by ExecInitRoutingInfo */
    1384                 :      256170 :     resultRelInfo->ri_PartitionTupleSlot = NULL;
    1385                 :      256170 :     resultRelInfo->ri_ChildToRootMap = NULL;
    1386                 :      256170 :     resultRelInfo->ri_ChildToRootMapValid = false;
    1387                 :      256170 :     resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
    1388                 :      256170 : }
    1389                 :             : 
    1390                 :             : /*
    1391                 :             :  * ExecGetTriggerResultRel
    1392                 :             :  *      Get a ResultRelInfo for a trigger target relation.
    1393                 :             :  *
    1394                 :             :  * Most of the time, triggers are fired on one of the result relations of the
    1395                 :             :  * query, and so we can just return a suitable one we already made and stored
    1396                 :             :  * in the es_opened_result_relations or es_tuple_routing_result_relations
    1397                 :             :  * Lists.
    1398                 :             :  *
    1399                 :             :  * However, it is sometimes necessary to fire triggers on other relations;
    1400                 :             :  * this happens mainly when an RI update trigger queues additional triggers
    1401                 :             :  * on other relations, which will be processed in the context of the outer
    1402                 :             :  * query.  For efficiency's sake, we want to have a ResultRelInfo for those
    1403                 :             :  * triggers too; that can avoid repeated re-opening of the relation.  (It
    1404                 :             :  * also provides a way for EXPLAIN ANALYZE to report the runtimes of such
    1405                 :             :  * triggers.)  So we make additional ResultRelInfo's as needed, and save them
    1406                 :             :  * in es_trig_target_relations.
    1407                 :             :  */
    1408                 :             : ResultRelInfo *
    1409                 :        5970 : ExecGetTriggerResultRel(EState *estate, Oid relid,
    1410                 :             :                         ResultRelInfo *rootRelInfo)
    1411                 :             : {
    1412                 :             :     ResultRelInfo *rInfo;
    1413                 :             :     ListCell   *l;
    1414                 :             :     Relation    rel;
    1415                 :             :     MemoryContext oldcontext;
    1416                 :             : 
    1417                 :             :     /*
    1418                 :             :      * Before creating a new ResultRelInfo, check if we've already made and
    1419                 :             :      * cached one for this relation.  We must ensure that the given
    1420                 :             :      * 'rootRelInfo' matches the one stored in the cached ResultRelInfo as
    1421                 :             :      * trigger handling for partitions can result in mixed requirements for
    1422                 :             :      * what ri_RootResultRelInfo is set to.
    1423                 :             :      */
    1424                 :             : 
    1425                 :             :     /* Search through the query result relations */
    1426   [ +  +  +  +  :        7847 :     foreach(l, estate->es_opened_result_relations)
                   +  + ]
    1427                 :             :     {
    1428                 :        6526 :         rInfo = lfirst(l);
    1429         [ +  + ]:        6526 :         if (RelationGetRelid(rInfo->ri_RelationDesc) == relid &&
    1430         [ +  + ]:        4911 :             rInfo->ri_RootResultRelInfo == rootRelInfo)
    1431                 :        4649 :             return rInfo;
    1432                 :             :     }
    1433                 :             : 
    1434                 :             :     /*
    1435                 :             :      * Search through the result relations that were created during tuple
    1436                 :             :      * routing, if any.
    1437                 :             :      */
    1438   [ +  +  +  +  :        2057 :     foreach(l, estate->es_tuple_routing_result_relations)
                   +  + ]
    1439                 :             :     {
    1440                 :         756 :         rInfo = (ResultRelInfo *) lfirst(l);
    1441         [ +  + ]:         756 :         if (RelationGetRelid(rInfo->ri_RelationDesc) == relid &&
    1442         [ +  + ]:         491 :             rInfo->ri_RootResultRelInfo == rootRelInfo)
    1443                 :          20 :             return rInfo;
    1444                 :             :     }
    1445                 :             : 
    1446                 :             :     /* Nope, but maybe we already made an extra ResultRelInfo for it */
    1447   [ +  +  +  +  :        1830 :     foreach(l, estate->es_trig_target_relations)
                   +  + ]
    1448                 :             :     {
    1449                 :         541 :         rInfo = (ResultRelInfo *) lfirst(l);
    1450         [ +  + ]:         541 :         if (RelationGetRelid(rInfo->ri_RelationDesc) == relid &&
    1451         [ +  + ]:          24 :             rInfo->ri_RootResultRelInfo == rootRelInfo)
    1452                 :          12 :             return rInfo;
    1453                 :             :     }
    1454                 :             :     /* Nope, so we need a new one */
    1455                 :             : 
    1456                 :             :     /*
    1457                 :             :      * Open the target relation's relcache entry.  We assume that an
    1458                 :             :      * appropriate lock is still held by the backend from whenever the trigger
    1459                 :             :      * event got queued, so we need take no new lock here.  Also, we need not
    1460                 :             :      * recheck the relkind, so no need for CheckValidResultRel.
    1461                 :             :      */
    1462                 :        1289 :     rel = table_open(relid, NoLock);
    1463                 :             : 
    1464                 :             :     /*
    1465                 :             :      * Make the new entry in the right context.
    1466                 :             :      */
    1467                 :        1289 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1468                 :        1289 :     rInfo = makeNode(ResultRelInfo);
    1469                 :        1289 :     InitResultRelInfo(rInfo,
    1470                 :             :                       rel,
    1471                 :             :                       0,        /* dummy rangetable index */
    1472                 :             :                       rootRelInfo,
    1473                 :             :                       estate->es_instrument);
    1474                 :        1289 :     estate->es_trig_target_relations =
    1475                 :        1289 :         lappend(estate->es_trig_target_relations, rInfo);
    1476                 :        1289 :     MemoryContextSwitchTo(oldcontext);
    1477                 :             : 
    1478                 :             :     /*
    1479                 :             :      * Currently, we don't need any index information in ResultRelInfos used
    1480                 :             :      * only for triggers, so no need to call ExecOpenIndices.
    1481                 :             :      */
    1482                 :             : 
    1483                 :        1289 :     return rInfo;
    1484                 :             : }
    1485                 :             : 
    1486                 :             : /*
    1487                 :             :  * Return the ancestor relations of a given leaf partition result relation
    1488                 :             :  * up to and including the query's root target relation.
    1489                 :             :  *
    1490                 :             :  * These work much like the ones opened by ExecGetTriggerResultRel, except
    1491                 :             :  * that we need to keep them in a separate list.
    1492                 :             :  *
    1493                 :             :  * These are closed by ExecCloseResultRelations.
    1494                 :             :  */
    1495                 :             : List *
    1496                 :         202 : ExecGetAncestorResultRels(EState *estate, ResultRelInfo *resultRelInfo)
    1497                 :             : {
    1498                 :         202 :     ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
    1499                 :         202 :     Relation    partRel = resultRelInfo->ri_RelationDesc;
    1500                 :             :     Oid         rootRelOid;
    1501                 :             : 
    1502         [ -  + ]:         202 :     if (!partRel->rd_rel->relispartition)
    1503         [ #  # ]:           0 :         elog(ERROR, "cannot find ancestors of a non-partition result relation");
    1504                 :             :     Assert(rootRelInfo != NULL);
    1505                 :         202 :     rootRelOid = RelationGetRelid(rootRelInfo->ri_RelationDesc);
    1506         [ +  + ]:         202 :     if (resultRelInfo->ri_ancestorResultRels == NIL)
    1507                 :             :     {
    1508                 :             :         ListCell   *lc;
    1509                 :         158 :         List       *oids = get_partition_ancestors(RelationGetRelid(partRel));
    1510                 :         158 :         List       *ancResultRels = NIL;
    1511                 :             : 
    1512   [ +  -  +  -  :         202 :         foreach(lc, oids)
                   +  - ]
    1513                 :             :         {
    1514                 :         202 :             Oid         ancOid = lfirst_oid(lc);
    1515                 :             :             Relation    ancRel;
    1516                 :             :             ResultRelInfo *rInfo;
    1517                 :             : 
    1518                 :             :             /*
    1519                 :             :              * Ignore the root ancestor here, and use ri_RootResultRelInfo
    1520                 :             :              * (below) for it instead.  Also, we stop climbing up the
    1521                 :             :              * hierarchy when we find the table that was mentioned in the
    1522                 :             :              * query.
    1523                 :             :              */
    1524         [ +  + ]:         202 :             if (ancOid == rootRelOid)
    1525                 :         158 :                 break;
    1526                 :             : 
    1527                 :             :             /*
    1528                 :             :              * All ancestors up to the root target relation must have been
    1529                 :             :              * locked by the planner or AcquireExecutorLocks().
    1530                 :             :              */
    1531                 :          44 :             ancRel = table_open(ancOid, NoLock);
    1532                 :          44 :             rInfo = makeNode(ResultRelInfo);
    1533                 :             : 
    1534                 :             :             /* dummy rangetable index */
    1535                 :          44 :             InitResultRelInfo(rInfo, ancRel, 0, NULL,
    1536                 :             :                               estate->es_instrument);
    1537                 :          44 :             ancResultRels = lappend(ancResultRels, rInfo);
    1538                 :             :         }
    1539                 :         158 :         ancResultRels = lappend(ancResultRels, rootRelInfo);
    1540                 :         158 :         resultRelInfo->ri_ancestorResultRels = ancResultRels;
    1541                 :             :     }
    1542                 :             : 
    1543                 :             :     /* We must have found some ancestor */
    1544                 :             :     Assert(resultRelInfo->ri_ancestorResultRels != NIL);
    1545                 :             : 
    1546                 :         202 :     return resultRelInfo->ri_ancestorResultRels;
    1547                 :             : }
    1548                 :             : 
    1549                 :             : /* ----------------------------------------------------------------
    1550                 :             :  *      ExecPostprocessPlan
    1551                 :             :  *
    1552                 :             :  *      Give plan nodes a final chance to execute before shutdown
    1553                 :             :  * ----------------------------------------------------------------
    1554                 :             :  */
    1555                 :             : static void
    1556                 :      324651 : ExecPostprocessPlan(EState *estate)
    1557                 :             : {
    1558                 :             :     ListCell   *lc;
    1559                 :             : 
    1560                 :             :     /*
    1561                 :             :      * Make sure nodes run forward.
    1562                 :             :      */
    1563                 :      324651 :     estate->es_direction = ForwardScanDirection;
    1564                 :             : 
    1565                 :             :     /*
    1566                 :             :      * Run any secondary ModifyTable nodes to completion, in case the main
    1567                 :             :      * query did not fetch all rows from them.  (We do this to ensure that
    1568                 :             :      * such nodes have predictable results.)
    1569                 :             :      */
    1570   [ +  +  +  +  :      325288 :     foreach(lc, estate->es_auxmodifytables)
                   +  + ]
    1571                 :             :     {
    1572                 :         637 :         PlanState  *ps = (PlanState *) lfirst(lc);
    1573                 :             : 
    1574                 :             :         for (;;)
    1575                 :         100 :         {
    1576                 :             :             TupleTableSlot *slot;
    1577                 :             : 
    1578                 :             :             /* Reset the per-output-tuple exprcontext each time */
    1579         [ +  + ]:         737 :             ResetPerTupleExprContext(estate);
    1580                 :             : 
    1581                 :         737 :             slot = ExecProcNode(ps);
    1582                 :             : 
    1583   [ +  +  +  - ]:         737 :             if (TupIsNull(slot))
    1584                 :             :                 break;
    1585                 :             :         }
    1586                 :             :     }
    1587                 :      324651 : }
    1588                 :             : 
    1589                 :             : /* ----------------------------------------------------------------
    1590                 :             :  *      ExecEndPlan
    1591                 :             :  *
    1592                 :             :  *      Cleans up the query plan -- closes files and frees up storage
    1593                 :             :  *
    1594                 :             :  * NOTE: we are no longer very worried about freeing storage per se
    1595                 :             :  * in this code; FreeExecutorState should be guaranteed to release all
    1596                 :             :  * memory that needs to be released.  What we are worried about doing
    1597                 :             :  * is closing relations and dropping buffer pins.  Thus, for example,
    1598                 :             :  * tuple tables must be cleared or dropped to ensure pins are released.
    1599                 :             :  * ----------------------------------------------------------------
    1600                 :             :  */
    1601                 :             : static void
    1602                 :      337981 : ExecEndPlan(PlanState *planstate, EState *estate)
    1603                 :             : {
    1604                 :             :     ListCell   *l;
    1605                 :             : 
    1606                 :             :     /*
    1607                 :             :      * shut down the node-type-specific query processing
    1608                 :             :      */
    1609                 :      337981 :     ExecEndNode(planstate);
    1610                 :             : 
    1611                 :             :     /*
    1612                 :             :      * for subplans too
    1613                 :             :      */
    1614   [ +  +  +  +  :      366458 :     foreach(l, estate->es_subplanstates)
                   +  + ]
    1615                 :             :     {
    1616                 :       28478 :         PlanState  *subplanstate = (PlanState *) lfirst(l);
    1617                 :             : 
    1618                 :       28478 :         ExecEndNode(subplanstate);
    1619                 :             :     }
    1620                 :             : 
    1621                 :             :     /*
    1622                 :             :      * destroy the executor's tuple table.  Actually we only care about
    1623                 :             :      * releasing buffer pins and tupdesc refcounts; there's no need to pfree
    1624                 :             :      * the TupleTableSlots, since the containing memory context is about to go
    1625                 :             :      * away anyway.
    1626                 :             :      */
    1627                 :      337980 :     ExecResetTupleTable(estate->es_tupleTable, false);
    1628                 :             : 
    1629                 :             :     /*
    1630                 :             :      * Close any Relations that have been opened for range table entries or
    1631                 :             :      * result relations.
    1632                 :             :      */
    1633                 :      337980 :     ExecCloseResultRelations(estate);
    1634                 :      337980 :     ExecCloseRangeTableRelations(estate);
    1635                 :      337980 : }
    1636                 :             : 
    1637                 :             : /*
    1638                 :             :  * Close any relations that have been opened for ResultRelInfos.
    1639                 :             :  */
    1640                 :             : void
    1641                 :      339251 : ExecCloseResultRelations(EState *estate)
    1642                 :             : {
    1643                 :             :     ListCell   *l;
    1644                 :             : 
    1645                 :             :     /*
    1646                 :             :      * close indexes of result relation(s) if any.  (Rels themselves are
    1647                 :             :      * closed in ExecCloseRangeTableRelations())
    1648                 :             :      *
    1649                 :             :      * In addition, close the stub RTs that may be in each resultrel's
    1650                 :             :      * ri_ancestorResultRels.
    1651                 :             :      */
    1652   [ +  +  +  +  :      413048 :     foreach(l, estate->es_opened_result_relations)
                   +  + ]
    1653                 :             :     {
    1654                 :       73797 :         ResultRelInfo *resultRelInfo = lfirst(l);
    1655                 :             :         ListCell   *lc;
    1656                 :             : 
    1657                 :       73797 :         ExecCloseIndices(resultRelInfo);
    1658   [ +  +  +  +  :       73967 :         foreach(lc, resultRelInfo->ri_ancestorResultRels)
                   +  + ]
    1659                 :             :         {
    1660                 :         170 :             ResultRelInfo *rInfo = lfirst(lc);
    1661                 :             : 
    1662                 :             :             /*
    1663                 :             :              * Ancestors with RTI > 0 (should only be the root ancestor) are
    1664                 :             :              * closed by ExecCloseRangeTableRelations.
    1665                 :             :              */
    1666         [ +  + ]:         170 :             if (rInfo->ri_RangeTableIndex > 0)
    1667                 :         138 :                 continue;
    1668                 :             : 
    1669                 :          32 :             table_close(rInfo->ri_RelationDesc, NoLock);
    1670                 :             :         }
    1671                 :             :     }
    1672                 :             : 
    1673                 :             :     /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
    1674   [ +  +  +  +  :      340173 :     foreach(l, estate->es_trig_target_relations)
                   +  + ]
    1675                 :             :     {
    1676                 :         922 :         ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
    1677                 :             : 
    1678                 :             :         /*
    1679                 :             :          * Assert this is a "dummy" ResultRelInfo, see above.  Otherwise we
    1680                 :             :          * might be issuing a duplicate close against a Relation opened by
    1681                 :             :          * ExecGetRangeTableRelation.
    1682                 :             :          */
    1683                 :             :         Assert(resultRelInfo->ri_RangeTableIndex == 0);
    1684                 :             : 
    1685                 :             :         /*
    1686                 :             :          * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
    1687                 :             :          * these rels, we needn't call ExecCloseIndices either.
    1688                 :             :          */
    1689                 :             :         Assert(resultRelInfo->ri_NumIndices == 0);
    1690                 :             : 
    1691                 :         922 :         table_close(resultRelInfo->ri_RelationDesc, NoLock);
    1692                 :             :     }
    1693                 :      339251 : }
    1694                 :             : 
    1695                 :             : /*
    1696                 :             :  * Close all relations opened by ExecGetRangeTableRelation().
    1697                 :             :  *
    1698                 :             :  * We do not release any locks we might hold on those rels.
    1699                 :             :  */
    1700                 :             : void
    1701                 :      338936 : ExecCloseRangeTableRelations(EState *estate)
    1702                 :             : {
    1703                 :             :     int         i;
    1704                 :             : 
    1705         [ +  + ]:     1043289 :     for (i = 0; i < estate->es_range_table_size; i++)
    1706                 :             :     {
    1707         [ +  + ]:      704353 :         if (estate->es_relations[i])
    1708                 :      347248 :             table_close(estate->es_relations[i], NoLock);
    1709                 :             :     }
    1710                 :      338936 : }
    1711                 :             : 
    1712                 :             : /* ----------------------------------------------------------------
    1713                 :             :  *      ExecutePlan
    1714                 :             :  *
    1715                 :             :  *      Processes the query plan until we have retrieved 'numberTuples' tuples,
    1716                 :             :  *      moving in the specified direction.
    1717                 :             :  *
    1718                 :             :  *      Runs to completion if numberTuples is 0
    1719                 :             :  * ----------------------------------------------------------------
    1720                 :             :  */
    1721                 :             : static void
    1722                 :      349067 : ExecutePlan(QueryDesc *queryDesc,
    1723                 :             :             CmdType operation,
    1724                 :             :             bool sendTuples,
    1725                 :             :             uint64 numberTuples,
    1726                 :             :             ScanDirection direction,
    1727                 :             :             DestReceiver *dest)
    1728                 :             : {
    1729                 :      349067 :     EState     *estate = queryDesc->estate;
    1730                 :      349067 :     PlanState  *planstate = queryDesc->planstate;
    1731                 :             :     bool        use_parallel_mode;
    1732                 :             :     TupleTableSlot *slot;
    1733                 :             :     uint64      current_tuple_count;
    1734                 :             : 
    1735                 :             :     /*
    1736                 :             :      * initialize local variables
    1737                 :             :      */
    1738                 :      349067 :     current_tuple_count = 0;
    1739                 :             : 
    1740                 :             :     /*
    1741                 :             :      * Set the direction.
    1742                 :             :      */
    1743                 :      349067 :     estate->es_direction = direction;
    1744                 :             : 
    1745                 :             :     /*
    1746                 :             :      * Set up parallel mode if appropriate.
    1747                 :             :      *
    1748                 :             :      * Parallel mode only supports complete execution of a plan.  If we've
    1749                 :             :      * already partially executed it, or if the caller asks us to exit early,
    1750                 :             :      * we must force the plan to run without parallelism.
    1751                 :             :      */
    1752   [ +  +  +  + ]:      349067 :     if (queryDesc->already_executed || numberTuples != 0)
    1753                 :       72235 :         use_parallel_mode = false;
    1754                 :             :     else
    1755                 :      276832 :         use_parallel_mode = queryDesc->plannedstmt->parallelModeNeeded;
    1756                 :      349067 :     queryDesc->already_executed = true;
    1757                 :             : 
    1758                 :      349067 :     estate->es_use_parallel_mode = use_parallel_mode;
    1759         [ +  + ]:      349067 :     if (use_parallel_mode)
    1760                 :         507 :         EnterParallelMode();
    1761                 :             : 
    1762                 :             :     /*
    1763                 :             :      * Loop until we've processed the proper number of tuples from the plan.
    1764                 :             :      */
    1765                 :             :     for (;;)
    1766                 :             :     {
    1767                 :             :         /* Reset the per-output-tuple exprcontext */
    1768         [ +  + ]:     8822468 :         ResetPerTupleExprContext(estate);
    1769                 :             : 
    1770                 :             :         /*
    1771                 :             :          * Execute the plan and obtain a tuple
    1772                 :             :          */
    1773                 :     8822468 :         slot = ExecProcNode(planstate);
    1774                 :             : 
    1775                 :             :         /*
    1776                 :             :          * if the tuple is null, then we assume there is nothing more to
    1777                 :             :          * process so we just end the loop...
    1778                 :             :          */
    1779   [ +  +  +  + ]:     8806917 :         if (TupIsNull(slot))
    1780                 :             :             break;
    1781                 :             : 
    1782                 :             :         /*
    1783                 :             :          * If we have a junk filter, then project a new tuple with the junk
    1784                 :             :          * removed.
    1785                 :             :          *
    1786                 :             :          * Store this new "clean" tuple in the junkfilter's resultSlot.
    1787                 :             :          * (Formerly, we stored it back over the "dirty" tuple, which is WRONG
    1788                 :             :          * because that tuple slot has the wrong descriptor.)
    1789                 :             :          */
    1790         [ +  + ]:     8525434 :         if (estate->es_junkFilter != NULL)
    1791                 :      175633 :             slot = ExecFilterJunk(estate->es_junkFilter, slot);
    1792                 :             : 
    1793                 :             :         /*
    1794                 :             :          * If we are supposed to send the tuple somewhere, do so. (In
    1795                 :             :          * practice, this is probably always the case at this point.)
    1796                 :             :          */
    1797         [ +  - ]:     8525434 :         if (sendTuples)
    1798                 :             :         {
    1799                 :             :             /*
    1800                 :             :              * If we are not able to send the tuple, we assume the destination
    1801                 :             :              * has closed and no more tuples can be sent. If that's the case,
    1802                 :             :              * end the loop.
    1803                 :             :              */
    1804         [ -  + ]:     8525434 :             if (!dest->receiveSlot(slot, dest))
    1805                 :           0 :                 break;
    1806                 :             :         }
    1807                 :             : 
    1808                 :             :         /*
    1809                 :             :          * Count tuples processed, if this is a SELECT.  (For other operation
    1810                 :             :          * types, the ModifyTable plan node must count the appropriate
    1811                 :             :          * events.)
    1812                 :             :          */
    1813         [ +  + ]:     8525426 :         if (operation == CMD_SELECT)
    1814                 :     8520718 :             (estate->es_processed)++;
    1815                 :             : 
    1816                 :             :         /*
    1817                 :             :          * check our tuple count.. if we've processed the proper number then
    1818                 :             :          * quit, else loop again and process more tuples.  Zero numberTuples
    1819                 :             :          * means no limit.
    1820                 :             :          */
    1821                 :     8525426 :         current_tuple_count++;
    1822   [ +  +  +  + ]:     8525426 :         if (numberTuples && numberTuples == current_tuple_count)
    1823                 :       52025 :             break;
    1824                 :             :     }
    1825                 :             : 
    1826                 :             :     /*
    1827                 :             :      * If we know we won't need to back up, we can release resources at this
    1828                 :             :      * point.
    1829                 :             :      */
    1830         [ +  + ]:      333508 :     if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))
    1831                 :      329023 :         ExecShutdownNode(planstate);
    1832                 :             : 
    1833         [ +  + ]:      333508 :     if (use_parallel_mode)
    1834                 :         499 :         ExitParallelMode();
    1835                 :      333508 : }
    1836                 :             : 
    1837                 :             : 
    1838                 :             : /*
    1839                 :             :  * ExecRelCheck --- check that tuple meets check constraints for result relation
    1840                 :             :  *
    1841                 :             :  * Returns NULL if OK, else name of failed check constraint
    1842                 :             :  */
    1843                 :             : static const char *
    1844                 :        1863 : ExecRelCheck(ResultRelInfo *resultRelInfo,
    1845                 :             :              TupleTableSlot *slot, EState *estate)
    1846                 :             : {
    1847                 :        1863 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    1848                 :        1863 :     int         ncheck = rel->rd_att->constr->num_check;
    1849                 :        1863 :     ConstrCheck *check = rel->rd_att->constr->check;
    1850                 :             :     ExprContext *econtext;
    1851                 :             :     MemoryContext oldContext;
    1852                 :             : 
    1853                 :             :     /*
    1854                 :             :      * CheckNNConstraintFetch let this pass with only a warning, but now we
    1855                 :             :      * should fail rather than possibly failing to enforce an important
    1856                 :             :      * constraint.
    1857                 :             :      */
    1858         [ -  + ]:        1863 :     if (ncheck != rel->rd_rel->relchecks)
    1859         [ #  # ]:           0 :         elog(ERROR, "%d pg_constraint record(s) missing for relation \"%s\"",
    1860                 :             :              rel->rd_rel->relchecks - ncheck, RelationGetRelationName(rel));
    1861                 :             : 
    1862                 :             :     /*
    1863                 :             :      * If first time through for this result relation, build expression
    1864                 :             :      * nodetrees for rel's constraint expressions.  Keep them in the per-query
    1865                 :             :      * memory context so they'll survive throughout the query.
    1866                 :             :      */
    1867         [ +  + ]:        1863 :     if (resultRelInfo->ri_CheckConstraintExprs == NULL)
    1868                 :             :     {
    1869                 :         974 :         oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
    1870                 :         974 :         resultRelInfo->ri_CheckConstraintExprs = palloc0_array(ExprState *, ncheck);
    1871         [ +  + ]:        2545 :         for (int i = 0; i < ncheck; i++)
    1872                 :             :         {
    1873                 :             :             Expr       *checkconstr;
    1874                 :             : 
    1875                 :             :             /* Skip not enforced constraint */
    1876         [ +  + ]:        1575 :             if (!check[i].ccenforced)
    1877                 :         216 :                 continue;
    1878                 :             : 
    1879                 :        1359 :             checkconstr = stringToNode(check[i].ccbin);
    1880                 :        1359 :             checkconstr = (Expr *) expand_generated_columns_in_expr((Node *) checkconstr, rel, 1);
    1881                 :        1355 :             resultRelInfo->ri_CheckConstraintExprs[i] =
    1882                 :        1359 :                 ExecPrepareExpr(checkconstr, estate);
    1883                 :             :         }
    1884                 :         970 :         MemoryContextSwitchTo(oldContext);
    1885                 :             :     }
    1886                 :             : 
    1887                 :             :     /*
    1888                 :             :      * We will use the EState's per-tuple context for evaluating constraint
    1889                 :             :      * expressions (creating it if it's not already there).
    1890                 :             :      */
    1891         [ +  + ]:        1859 :     econtext = GetPerTupleExprContext(estate);
    1892                 :             : 
    1893                 :             :     /* Arrange for econtext's scan tuple to be the tuple under test */
    1894                 :        1859 :     econtext->ecxt_scantuple = slot;
    1895                 :             : 
    1896                 :             :     /* And evaluate the constraints */
    1897         [ +  + ]:        4283 :     for (int i = 0; i < ncheck; i++)
    1898                 :             :     {
    1899                 :        2756 :         ExprState  *checkconstr = resultRelInfo->ri_CheckConstraintExprs[i];
    1900                 :             : 
    1901                 :             :         /*
    1902                 :             :          * NOTE: SQL specifies that a NULL result from a constraint expression
    1903                 :             :          * is not to be treated as a failure.  Therefore, use ExecCheck not
    1904                 :             :          * ExecQual.
    1905                 :             :          */
    1906   [ +  +  +  + ]:        2756 :         if (checkconstr && !ExecCheck(checkconstr, econtext))
    1907                 :         332 :             return check[i].ccname;
    1908                 :             :     }
    1909                 :             : 
    1910                 :             :     /* NULL result means no error */
    1911                 :        1527 :     return NULL;
    1912                 :             : }
    1913                 :             : 
    1914                 :             : /*
    1915                 :             :  * ExecPartitionCheck --- check that tuple meets the partition constraint.
    1916                 :             :  *
    1917                 :             :  * Returns true if it meets the partition constraint.  If the constraint
    1918                 :             :  * fails and we're asked to emit an error, do so and don't return; otherwise
    1919                 :             :  * return false.
    1920                 :             :  */
    1921                 :             : bool
    1922                 :        8713 : ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
    1923                 :             :                    EState *estate, bool emitError)
    1924                 :             : {
    1925                 :             :     ExprContext *econtext;
    1926                 :             :     bool        success;
    1927                 :             : 
    1928                 :             :     /*
    1929                 :             :      * If first time through, build expression state tree for the partition
    1930                 :             :      * check expression.  (In the corner case where the partition check
    1931                 :             :      * expression is empty, ie there's a default partition and nothing else,
    1932                 :             :      * we'll be fooled into executing this code each time through.  But it's
    1933                 :             :      * pretty darn cheap in that case, so we don't worry about it.)
    1934                 :             :      */
    1935         [ +  + ]:        8713 :     if (resultRelInfo->ri_PartitionCheckExpr == NULL)
    1936                 :             :     {
    1937                 :             :         /*
    1938                 :             :          * Ensure that the qual tree and prepared expression are in the
    1939                 :             :          * query-lifespan context.
    1940                 :             :          */
    1941                 :        2527 :         MemoryContext oldcxt = MemoryContextSwitchTo(estate->es_query_cxt);
    1942                 :        2527 :         List       *qual = RelationGetPartitionQual(resultRelInfo->ri_RelationDesc);
    1943                 :             : 
    1944                 :        2527 :         resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
    1945                 :        2527 :         MemoryContextSwitchTo(oldcxt);
    1946                 :             :     }
    1947                 :             : 
    1948                 :             :     /*
    1949                 :             :      * We will use the EState's per-tuple context for evaluating constraint
    1950                 :             :      * expressions (creating it if it's not already there).
    1951                 :             :      */
    1952         [ +  + ]:        8713 :     econtext = GetPerTupleExprContext(estate);
    1953                 :             : 
    1954                 :             :     /* Arrange for econtext's scan tuple to be the tuple under test */
    1955                 :        8713 :     econtext->ecxt_scantuple = slot;
    1956                 :             : 
    1957                 :             :     /*
    1958                 :             :      * As in case of the cataloged constraints, we treat a NULL result as
    1959                 :             :      * success here, not a failure.
    1960                 :             :      */
    1961                 :        8713 :     success = ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
    1962                 :             : 
    1963                 :             :     /* if asked to emit error, don't actually return on failure */
    1964   [ +  +  +  + ]:        8713 :     if (!success && emitError)
    1965                 :         134 :         ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
    1966                 :             : 
    1967                 :        8579 :     return success;
    1968                 :             : }
    1969                 :             : 
    1970                 :             : /*
    1971                 :             :  * ExecPartitionCheckEmitError - Form and emit an error message after a failed
    1972                 :             :  * partition constraint check.
    1973                 :             :  */
    1974                 :             : void
    1975                 :         166 : ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
    1976                 :             :                             TupleTableSlot *slot,
    1977                 :             :                             EState *estate)
    1978                 :             : {
    1979                 :             :     Oid         root_relid;
    1980                 :             :     TupleDesc   tupdesc;
    1981                 :             :     char       *val_desc;
    1982                 :             :     Bitmapset  *modifiedCols;
    1983                 :             : 
    1984                 :             :     /*
    1985                 :             :      * If the tuple has been routed, it's been converted to the partition's
    1986                 :             :      * rowtype, which might differ from the root table's.  We must convert it
    1987                 :             :      * back to the root table's rowtype so that val_desc in the error message
    1988                 :             :      * matches the input tuple.
    1989                 :             :      */
    1990         [ +  + ]:         166 :     if (resultRelInfo->ri_RootResultRelInfo)
    1991                 :             :     {
    1992                 :          13 :         ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
    1993                 :             :         TupleDesc   old_tupdesc;
    1994                 :             :         AttrMap    *map;
    1995                 :             : 
    1996                 :          13 :         root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
    1997                 :          13 :         tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
    1998                 :             : 
    1999                 :          13 :         old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
    2000                 :             :         /* a reverse map */
    2001                 :          13 :         map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc, false);
    2002                 :             : 
    2003                 :             :         /*
    2004                 :             :          * Partition-specific slot's tupdesc can't be changed, so allocate a
    2005                 :             :          * new one.
    2006                 :             :          */
    2007         [ +  + ]:          13 :         if (map != NULL)
    2008                 :           5 :             slot = execute_attr_map_slot(map, slot,
    2009                 :             :                                          MakeTupleTableSlot(tupdesc, &TTSOpsVirtual, 0));
    2010                 :          13 :         modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
    2011                 :          13 :                                  ExecGetUpdatedCols(rootrel, estate));
    2012                 :             :     }
    2013                 :             :     else
    2014                 :             :     {
    2015                 :         153 :         root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
    2016                 :         153 :         tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
    2017                 :         153 :         modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
    2018                 :         153 :                                  ExecGetUpdatedCols(resultRelInfo, estate));
    2019                 :             :     }
    2020                 :             : 
    2021                 :         166 :     val_desc = ExecBuildSlotValueDescription(root_relid,
    2022                 :             :                                              slot,
    2023                 :             :                                              tupdesc,
    2024                 :             :                                              modifiedCols,
    2025                 :             :                                              64);
    2026   [ +  -  +  - ]:         166 :     ereport(ERROR,
    2027                 :             :             (errcode(ERRCODE_CHECK_VIOLATION),
    2028                 :             :              errmsg("new row for relation \"%s\" violates partition constraint",
    2029                 :             :                     RelationGetRelationName(resultRelInfo->ri_RelationDesc)),
    2030                 :             :              val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
    2031                 :             :              errtable(resultRelInfo->ri_RelationDesc)));
    2032                 :             : }
    2033                 :             : 
    2034                 :             : /*
    2035                 :             :  * ExecConstraints - check constraints of the tuple in 'slot'
    2036                 :             :  *
    2037                 :             :  * This checks the traditional NOT NULL and check constraints.
    2038                 :             :  *
    2039                 :             :  * The partition constraint is *NOT* checked.
    2040                 :             :  *
    2041                 :             :  * Note: 'slot' contains the tuple to check the constraints of, which may
    2042                 :             :  * have been converted from the original input tuple after tuple routing.
    2043                 :             :  * 'resultRelInfo' is the final result relation, after tuple routing.
    2044                 :             :  */
    2045                 :             : void
    2046                 :     2979020 : ExecConstraints(ResultRelInfo *resultRelInfo,
    2047                 :             :                 TupleTableSlot *slot, EState *estate)
    2048                 :             : {
    2049                 :     2979020 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    2050                 :     2979020 :     TupleDesc   tupdesc = RelationGetDescr(rel);
    2051                 :     2979020 :     TupleConstr *constr = tupdesc->constr;
    2052                 :             :     Bitmapset  *modifiedCols;
    2053                 :     2979020 :     List       *notnull_virtual_attrs = NIL;
    2054                 :             : 
    2055                 :             :     Assert(constr);             /* we should not be called otherwise */
    2056                 :             : 
    2057                 :             :     /*
    2058                 :             :      * Verify not-null constraints.
    2059                 :             :      *
    2060                 :             :      * Not-null constraints on virtual generated columns are collected and
    2061                 :             :      * checked separately below.
    2062                 :             :      */
    2063         [ +  + ]:     2979020 :     if (constr->has_not_null)
    2064                 :             :     {
    2065         [ +  + ]:    11012640 :         for (AttrNumber attnum = 1; attnum <= tupdesc->natts; attnum++)
    2066                 :             :         {
    2067                 :     8038088 :             Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
    2068                 :             : 
    2069   [ +  +  +  + ]:     8038088 :             if (att->attnotnull && att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
    2070                 :          72 :                 notnull_virtual_attrs = lappend_int(notnull_virtual_attrs, attnum);
    2071   [ +  +  +  + ]:     8038016 :             else if (att->attnotnull && slot_attisnull(slot, attnum))
    2072                 :         229 :                 ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
    2073                 :             :         }
    2074                 :             :     }
    2075                 :             : 
    2076                 :             :     /*
    2077                 :             :      * Verify not-null constraints on virtual generated column, if any.
    2078                 :             :      */
    2079         [ +  + ]:     2978791 :     if (notnull_virtual_attrs)
    2080                 :             :     {
    2081                 :             :         AttrNumber  attnum;
    2082                 :             : 
    2083                 :          72 :         attnum = ExecRelGenVirtualNotNull(resultRelInfo, slot, estate,
    2084                 :             :                                           notnull_virtual_attrs);
    2085         [ +  + ]:          72 :         if (attnum != InvalidAttrNumber)
    2086                 :          28 :             ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
    2087                 :             :     }
    2088                 :             : 
    2089                 :             :     /*
    2090                 :             :      * Verify check constraints.
    2091                 :             :      */
    2092         [ +  + ]:     2978763 :     if (rel->rd_rel->relchecks > 0)
    2093                 :             :     {
    2094                 :             :         const char *failed;
    2095                 :             : 
    2096         [ +  + ]:        1863 :         if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
    2097                 :             :         {
    2098                 :             :             char       *val_desc;
    2099                 :         332 :             Relation    orig_rel = rel;
    2100                 :             : 
    2101                 :             :             /*
    2102                 :             :              * If the tuple has been routed, it's been converted to the
    2103                 :             :              * partition's rowtype, which might differ from the root table's.
    2104                 :             :              * We must convert it back to the root table's rowtype so that
    2105                 :             :              * val_desc shown error message matches the input tuple.
    2106                 :             :              */
    2107         [ +  + ]:         332 :             if (resultRelInfo->ri_RootResultRelInfo)
    2108                 :             :             {
    2109                 :          68 :                 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
    2110                 :          68 :                 TupleDesc   old_tupdesc = RelationGetDescr(rel);
    2111                 :             :                 AttrMap    *map;
    2112                 :             : 
    2113                 :          68 :                 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
    2114                 :             :                 /* a reverse map */
    2115                 :          68 :                 map = build_attrmap_by_name_if_req(old_tupdesc,
    2116                 :             :                                                    tupdesc,
    2117                 :             :                                                    false);
    2118                 :             : 
    2119                 :             :                 /*
    2120                 :             :                  * Partition-specific slot's tupdesc can't be changed, so
    2121                 :             :                  * allocate a new one.
    2122                 :             :                  */
    2123         [ +  + ]:          68 :                 if (map != NULL)
    2124                 :          40 :                     slot = execute_attr_map_slot(map, slot,
    2125                 :             :                                                  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual, 0));
    2126                 :          68 :                 modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
    2127                 :          68 :                                          ExecGetUpdatedCols(rootrel, estate));
    2128                 :          68 :                 rel = rootrel->ri_RelationDesc;
    2129                 :             :             }
    2130                 :             :             else
    2131                 :         264 :                 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
    2132                 :         264 :                                          ExecGetUpdatedCols(resultRelInfo, estate));
    2133                 :         332 :             val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
    2134                 :             :                                                      slot,
    2135                 :             :                                                      tupdesc,
    2136                 :             :                                                      modifiedCols,
    2137                 :             :                                                      64);
    2138   [ +  -  +  - ]:         332 :             ereport(ERROR,
    2139                 :             :                     (errcode(ERRCODE_CHECK_VIOLATION),
    2140                 :             :                      errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
    2141                 :             :                             RelationGetRelationName(orig_rel), failed),
    2142                 :             :                      val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
    2143                 :             :                      errtableconstraint(orig_rel, failed)));
    2144                 :             :         }
    2145                 :             :     }
    2146                 :     2978427 : }
    2147                 :             : 
    2148                 :             : /*
    2149                 :             :  * Verify not-null constraints on virtual generated columns of the given
    2150                 :             :  * tuple slot.
    2151                 :             :  *
    2152                 :             :  * Return value of InvalidAttrNumber means all not-null constraints on virtual
    2153                 :             :  * generated columns are satisfied.  A return value > 0 means a not-null
    2154                 :             :  * violation happened for that attribute.
    2155                 :             :  *
    2156                 :             :  * notnull_virtual_attrs is the list of the attnums of virtual generated column with
    2157                 :             :  * not-null constraints.
    2158                 :             :  */
    2159                 :             : AttrNumber
    2160                 :         132 : ExecRelGenVirtualNotNull(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
    2161                 :             :                          EState *estate, List *notnull_virtual_attrs)
    2162                 :             : {
    2163                 :         132 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    2164                 :             :     ExprContext *econtext;
    2165                 :             :     MemoryContext oldContext;
    2166                 :             : 
    2167                 :             :     /*
    2168                 :             :      * We implement this by building a NullTest node for each virtual
    2169                 :             :      * generated column, which we cache in resultRelInfo, and running those
    2170                 :             :      * through ExecCheck().
    2171                 :             :      */
    2172         [ +  + ]:         132 :     if (resultRelInfo->ri_GenVirtualNotNullConstraintExprs == NULL)
    2173                 :             :     {
    2174                 :         100 :         oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
    2175                 :         100 :         resultRelInfo->ri_GenVirtualNotNullConstraintExprs =
    2176                 :         100 :             palloc0_array(ExprState *, list_length(notnull_virtual_attrs));
    2177                 :             : 
    2178   [ +  -  +  +  :         320 :         foreach_int(attnum, notnull_virtual_attrs)
                   +  + ]
    2179                 :             :         {
    2180                 :         120 :             int         i = foreach_current_index(attnum);
    2181                 :             :             NullTest   *nnulltest;
    2182                 :             : 
    2183                 :             :             /* "generated_expression IS NOT NULL" check. */
    2184                 :         120 :             nnulltest = makeNode(NullTest);
    2185                 :         120 :             nnulltest->arg = (Expr *) build_generation_expression(rel, attnum);
    2186                 :         120 :             nnulltest->nulltesttype = IS_NOT_NULL;
    2187                 :         120 :             nnulltest->argisrow = false;
    2188                 :         120 :             nnulltest->location = -1;
    2189                 :             : 
    2190                 :         120 :             resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i] =
    2191                 :         120 :                 ExecPrepareExpr((Expr *) nnulltest, estate);
    2192                 :             :         }
    2193                 :         100 :         MemoryContextSwitchTo(oldContext);
    2194                 :             :     }
    2195                 :             : 
    2196                 :             :     /*
    2197                 :             :      * We will use the EState's per-tuple context for evaluating virtual
    2198                 :             :      * generated column not null constraint expressions (creating it if it's
    2199                 :             :      * not already there).
    2200                 :             :      */
    2201         [ +  + ]:         132 :     econtext = GetPerTupleExprContext(estate);
    2202                 :             : 
    2203                 :             :     /* Arrange for econtext's scan tuple to be the tuple under test */
    2204                 :         132 :     econtext->ecxt_scantuple = slot;
    2205                 :             : 
    2206                 :             :     /* And evaluate the check constraints for virtual generated column */
    2207   [ +  -  +  +  :         336 :     foreach_int(attnum, notnull_virtual_attrs)
                   +  + ]
    2208                 :             :     {
    2209                 :         168 :         int         i = foreach_current_index(attnum);
    2210                 :         168 :         ExprState  *exprstate = resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i];
    2211                 :             : 
    2212                 :             :         Assert(exprstate != NULL);
    2213         [ +  + ]:         168 :         if (!ExecCheck(exprstate, econtext))
    2214                 :          48 :             return attnum;
    2215                 :             :     }
    2216                 :             : 
    2217                 :             :     /* InvalidAttrNumber result means no error */
    2218                 :          84 :     return InvalidAttrNumber;
    2219                 :             : }
    2220                 :             : 
    2221                 :             : /*
    2222                 :             :  * Report a violation of a not-null constraint that was already detected.
    2223                 :             :  */
    2224                 :             : static void
    2225                 :         257 : ReportNotNullViolationError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
    2226                 :             :                             EState *estate, int attnum)
    2227                 :             : {
    2228                 :             :     Bitmapset  *modifiedCols;
    2229                 :             :     char       *val_desc;
    2230                 :         257 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    2231                 :         257 :     Relation    orig_rel = rel;
    2232                 :         257 :     TupleDesc   tupdesc = RelationGetDescr(rel);
    2233                 :         257 :     TupleDesc   orig_tupdesc = RelationGetDescr(rel);
    2234                 :         257 :     Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
    2235                 :             : 
    2236                 :             :     Assert(attnum > 0);
    2237                 :             : 
    2238                 :             :     /*
    2239                 :             :      * If the tuple has been routed, it's been converted to the partition's
    2240                 :             :      * rowtype, which might differ from the root table's.  We must convert it
    2241                 :             :      * back to the root table's rowtype so that val_desc shown error message
    2242                 :             :      * matches the input tuple.
    2243                 :             :      */
    2244         [ +  + ]:         257 :     if (resultRelInfo->ri_RootResultRelInfo)
    2245                 :             :     {
    2246                 :          56 :         ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
    2247                 :             :         AttrMap    *map;
    2248                 :             : 
    2249                 :          56 :         tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
    2250                 :             :         /* a reverse map */
    2251                 :          56 :         map = build_attrmap_by_name_if_req(orig_tupdesc,
    2252                 :             :                                            tupdesc,
    2253                 :             :                                            false);
    2254                 :             : 
    2255                 :             :         /*
    2256                 :             :          * Partition-specific slot's tupdesc can't be changed, so allocate a
    2257                 :             :          * new one.
    2258                 :             :          */
    2259         [ +  + ]:          56 :         if (map != NULL)
    2260                 :          28 :             slot = execute_attr_map_slot(map, slot,
    2261                 :             :                                          MakeTupleTableSlot(tupdesc, &TTSOpsVirtual, 0));
    2262                 :          56 :         modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
    2263                 :          56 :                                  ExecGetUpdatedCols(rootrel, estate));
    2264                 :          56 :         rel = rootrel->ri_RelationDesc;
    2265                 :             :     }
    2266                 :             :     else
    2267                 :         201 :         modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
    2268                 :         201 :                                  ExecGetUpdatedCols(resultRelInfo, estate));
    2269                 :             : 
    2270                 :         257 :     val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
    2271                 :             :                                              slot,
    2272                 :             :                                              tupdesc,
    2273                 :             :                                              modifiedCols,
    2274                 :             :                                              64);
    2275   [ +  -  +  - ]:         257 :     ereport(ERROR,
    2276                 :             :             errcode(ERRCODE_NOT_NULL_VIOLATION),
    2277                 :             :             errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
    2278                 :             :                    NameStr(att->attname),
    2279                 :             :                    RelationGetRelationName(orig_rel)),
    2280                 :             :             val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
    2281                 :             :             errtablecol(orig_rel, attnum));
    2282                 :             : }
    2283                 :             : 
    2284                 :             : /*
    2285                 :             :  * ExecWithCheckOptions -- check that tuple satisfies any WITH CHECK OPTIONs
    2286                 :             :  * of the specified kind.
    2287                 :             :  *
    2288                 :             :  * Note that this needs to be called multiple times to ensure that all kinds of
    2289                 :             :  * WITH CHECK OPTIONs are handled (both those from views which have the WITH
    2290                 :             :  * CHECK OPTION set and from row-level security policies).  See ExecInsert()
    2291                 :             :  * and ExecUpdate().
    2292                 :             :  */
    2293                 :             : void
    2294                 :        1609 : ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
    2295                 :             :                      TupleTableSlot *slot, EState *estate)
    2296                 :             : {
    2297                 :        1609 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    2298                 :        1609 :     TupleDesc   tupdesc = RelationGetDescr(rel);
    2299                 :             :     ExprContext *econtext;
    2300                 :             :     ListCell   *l1,
    2301                 :             :                *l2;
    2302                 :             : 
    2303                 :             :     /*
    2304                 :             :      * We will use the EState's per-tuple context for evaluating constraint
    2305                 :             :      * expressions (creating it if it's not already there).
    2306                 :             :      */
    2307         [ +  + ]:        1609 :     econtext = GetPerTupleExprContext(estate);
    2308                 :             : 
    2309                 :             :     /* Arrange for econtext's scan tuple to be the tuple under test */
    2310                 :        1609 :     econtext->ecxt_scantuple = slot;
    2311                 :             : 
    2312                 :             :     /* Check each of the constraints */
    2313   [ +  -  +  +  :        4438 :     forboth(l1, resultRelInfo->ri_WithCheckOptions,
          +  -  +  +  +  
             +  +  -  +  
                      + ]
    2314                 :             :             l2, resultRelInfo->ri_WithCheckOptionExprs)
    2315                 :             :     {
    2316                 :        3179 :         WithCheckOption *wco = (WithCheckOption *) lfirst(l1);
    2317                 :        3179 :         ExprState  *wcoExpr = (ExprState *) lfirst(l2);
    2318                 :             : 
    2319                 :             :         /*
    2320                 :             :          * Skip any WCOs which are not the kind we are looking for at this
    2321                 :             :          * time.
    2322                 :             :          */
    2323         [ +  + ]:        3179 :         if (wco->kind != kind)
    2324                 :        1912 :             continue;
    2325                 :             : 
    2326                 :             :         /*
    2327                 :             :          * WITH CHECK OPTION checks are intended to ensure that the new tuple
    2328                 :             :          * is visible (in the case of a view) or that it passes the
    2329                 :             :          * 'with-check' policy (in the case of row security). If the qual
    2330                 :             :          * evaluates to NULL or FALSE, then the new tuple won't be included in
    2331                 :             :          * the view or doesn't pass the 'with-check' policy for the table.
    2332                 :             :          */
    2333         [ +  + ]:        1267 :         if (!ExecQual(wcoExpr, econtext))
    2334                 :             :         {
    2335                 :             :             char       *val_desc;
    2336                 :             :             Bitmapset  *modifiedCols;
    2337                 :             : 
    2338   [ +  +  +  +  :         350 :             switch (wco->kind)
                      - ]
    2339                 :             :             {
    2340                 :             :                     /*
    2341                 :             :                      * For WITH CHECK OPTIONs coming from views, we might be
    2342                 :             :                      * able to provide the details on the row, depending on
    2343                 :             :                      * the permissions on the relation (that is, if the user
    2344                 :             :                      * could view it directly anyway).  For RLS violations, we
    2345                 :             :                      * don't include the data since we don't know if the user
    2346                 :             :                      * should be able to view the tuple as that depends on the
    2347                 :             :                      * USING policy.
    2348                 :             :                      */
    2349                 :         150 :                 case WCO_VIEW_CHECK:
    2350                 :             :                     /* See the comment in ExecConstraints(). */
    2351         [ +  + ]:         150 :                     if (resultRelInfo->ri_RootResultRelInfo)
    2352                 :             :                     {
    2353                 :          27 :                         ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
    2354                 :          27 :                         TupleDesc   old_tupdesc = RelationGetDescr(rel);
    2355                 :             :                         AttrMap    *map;
    2356                 :             : 
    2357                 :          27 :                         tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
    2358                 :             :                         /* a reverse map */
    2359                 :          27 :                         map = build_attrmap_by_name_if_req(old_tupdesc,
    2360                 :             :                                                            tupdesc,
    2361                 :             :                                                            false);
    2362                 :             : 
    2363                 :             :                         /*
    2364                 :             :                          * Partition-specific slot's tupdesc can't be changed,
    2365                 :             :                          * so allocate a new one.
    2366                 :             :                          */
    2367         [ +  + ]:          27 :                         if (map != NULL)
    2368                 :          16 :                             slot = execute_attr_map_slot(map, slot,
    2369                 :             :                                                          MakeTupleTableSlot(tupdesc, &TTSOpsVirtual, 0));
    2370                 :             : 
    2371                 :          27 :                         modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
    2372                 :          27 :                                                  ExecGetUpdatedCols(rootrel, estate));
    2373                 :          27 :                         rel = rootrel->ri_RelationDesc;
    2374                 :             :                     }
    2375                 :             :                     else
    2376                 :         123 :                         modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
    2377                 :         123 :                                                  ExecGetUpdatedCols(resultRelInfo, estate));
    2378                 :         150 :                     val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
    2379                 :             :                                                              slot,
    2380                 :             :                                                              tupdesc,
    2381                 :             :                                                              modifiedCols,
    2382                 :             :                                                              64);
    2383                 :             : 
    2384   [ +  -  +  - ]:         150 :                     ereport(ERROR,
    2385                 :             :                             (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),
    2386                 :             :                              errmsg("new row violates check option for view \"%s\"",
    2387                 :             :                                     wco->relname),
    2388                 :             :                              val_desc ? errdetail("Failing row contains %s.",
    2389                 :             :                                                   val_desc) : 0));
    2390                 :             :                     break;
    2391                 :         164 :                 case WCO_RLS_INSERT_CHECK:
    2392                 :             :                 case WCO_RLS_UPDATE_CHECK:
    2393         [ +  + ]:         164 :                     if (wco->polname != NULL)
    2394         [ +  - ]:          39 :                         ereport(ERROR,
    2395                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2396                 :             :                                  errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
    2397                 :             :                                         wco->polname, wco->relname)));
    2398                 :             :                     else
    2399         [ +  - ]:         125 :                         ereport(ERROR,
    2400                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2401                 :             :                                  errmsg("new row violates row-level security policy for table \"%s\"",
    2402                 :             :                                         wco->relname)));
    2403                 :             :                     break;
    2404                 :          16 :                 case WCO_RLS_MERGE_UPDATE_CHECK:
    2405                 :             :                 case WCO_RLS_MERGE_DELETE_CHECK:
    2406         [ -  + ]:          16 :                     if (wco->polname != NULL)
    2407         [ #  # ]:           0 :                         ereport(ERROR,
    2408                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2409                 :             :                                  errmsg("target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
    2410                 :             :                                         wco->polname, wco->relname)));
    2411                 :             :                     else
    2412         [ +  - ]:          16 :                         ereport(ERROR,
    2413                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2414                 :             :                                  errmsg("target row violates row-level security policy (USING expression) for table \"%s\"",
    2415                 :             :                                         wco->relname)));
    2416                 :             :                     break;
    2417                 :          20 :                 case WCO_RLS_CONFLICT_CHECK:
    2418         [ -  + ]:          20 :                     if (wco->polname != NULL)
    2419         [ #  # ]:           0 :                         ereport(ERROR,
    2420                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2421                 :             :                                  errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
    2422                 :             :                                         wco->polname, wco->relname)));
    2423                 :             :                     else
    2424         [ +  - ]:          20 :                         ereport(ERROR,
    2425                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2426                 :             :                                  errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
    2427                 :             :                                         wco->relname)));
    2428                 :             :                     break;
    2429                 :           0 :                 default:
    2430         [ #  # ]:           0 :                     elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
    2431                 :             :                     break;
    2432                 :             :             }
    2433                 :             :         }
    2434                 :             :     }
    2435                 :        1259 : }
    2436                 :             : 
    2437                 :             : /*
    2438                 :             :  * ExecBuildSlotValueDescription -- construct a string representing a tuple
    2439                 :             :  *
    2440                 :             :  * This is intentionally very similar to BuildIndexValueDescription, but
    2441                 :             :  * unlike that function, we truncate long field values (to at most maxfieldlen
    2442                 :             :  * bytes).  That seems necessary here since heap field values could be very
    2443                 :             :  * long, whereas index entries typically aren't so wide.
    2444                 :             :  *
    2445                 :             :  * Also, unlike the case with index entries, we need to be prepared to ignore
    2446                 :             :  * dropped columns.  We used to use the slot's tuple descriptor to decode the
    2447                 :             :  * data, but the slot's descriptor doesn't identify dropped columns, so we
    2448                 :             :  * now need to be passed the relation's descriptor.
    2449                 :             :  *
    2450                 :             :  * Note that, like BuildIndexValueDescription, if the user does not have
    2451                 :             :  * permission to view any of the columns involved, a NULL is returned.  Unlike
    2452                 :             :  * BuildIndexValueDescription, if the user has access to view a subset of the
    2453                 :             :  * column involved, that subset will be returned with a key identifying which
    2454                 :             :  * columns they are.
    2455                 :             :  */
    2456                 :             : char *
    2457                 :        1059 : ExecBuildSlotValueDescription(Oid reloid,
    2458                 :             :                               TupleTableSlot *slot,
    2459                 :             :                               TupleDesc tupdesc,
    2460                 :             :                               Bitmapset *modifiedCols,
    2461                 :             :                               int maxfieldlen)
    2462                 :             : {
    2463                 :             :     StringInfoData buf;
    2464                 :             :     StringInfoData collist;
    2465                 :        1059 :     bool        write_comma = false;
    2466                 :        1059 :     bool        write_comma_collist = false;
    2467                 :             :     int         i;
    2468                 :             :     AclResult   aclresult;
    2469                 :        1059 :     bool        table_perm = false;
    2470                 :        1059 :     bool        any_perm = false;
    2471                 :             : 
    2472                 :             :     /*
    2473                 :             :      * Check if RLS is enabled and should be active for the relation; if so,
    2474                 :             :      * then don't return anything.  Otherwise, go through normal permission
    2475                 :             :      * checks.
    2476                 :             :      */
    2477         [ -  + ]:        1059 :     if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
    2478                 :           0 :         return NULL;
    2479                 :             : 
    2480                 :        1059 :     initStringInfo(&buf);
    2481                 :             : 
    2482                 :        1059 :     appendStringInfoChar(&buf, '(');
    2483                 :             : 
    2484                 :             :     /*
    2485                 :             :      * Check if the user has permissions to see the row.  Table-level SELECT
    2486                 :             :      * allows access to all columns.  If the user does not have table-level
    2487                 :             :      * SELECT then we check each column and include those the user has SELECT
    2488                 :             :      * rights on.  Additionally, we always include columns the user provided
    2489                 :             :      * data for.
    2490                 :             :      */
    2491                 :        1059 :     aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
    2492         [ +  + ]:        1059 :     if (aclresult != ACLCHECK_OK)
    2493                 :             :     {
    2494                 :             :         /* Set up the buffer for the column list */
    2495                 :          40 :         initStringInfo(&collist);
    2496                 :          40 :         appendStringInfoChar(&collist, '(');
    2497                 :             :     }
    2498                 :             :     else
    2499                 :        1019 :         table_perm = any_perm = true;
    2500                 :             : 
    2501                 :             :     /* Make sure the tuple is fully deconstructed */
    2502                 :        1059 :     slot_getallattrs(slot);
    2503                 :             : 
    2504         [ +  + ]:        3816 :     for (i = 0; i < tupdesc->natts; i++)
    2505                 :             :     {
    2506                 :        2757 :         bool        column_perm = false;
    2507                 :             :         char       *val;
    2508                 :             :         int         vallen;
    2509                 :        2757 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
    2510                 :             : 
    2511                 :             :         /* ignore dropped columns */
    2512         [ +  + ]:        2757 :         if (att->attisdropped)
    2513                 :          25 :             continue;
    2514                 :             : 
    2515         [ +  + ]:        2732 :         if (!table_perm)
    2516                 :             :         {
    2517                 :             :             /*
    2518                 :             :              * No table-level SELECT, so need to make sure they either have
    2519                 :             :              * SELECT rights on the column or that they have provided the data
    2520                 :             :              * for the column.  If not, omit this column from the error
    2521                 :             :              * message.
    2522                 :             :              */
    2523                 :         156 :             aclresult = pg_attribute_aclcheck(reloid, att->attnum,
    2524                 :             :                                               GetUserId(), ACL_SELECT);
    2525         [ +  + ]:         156 :             if (bms_is_member(att->attnum - FirstLowInvalidHeapAttributeNumber,
    2526         [ +  + ]:          92 :                               modifiedCols) || aclresult == ACLCHECK_OK)
    2527                 :             :             {
    2528                 :          96 :                 column_perm = any_perm = true;
    2529                 :             : 
    2530         [ +  + ]:          96 :                 if (write_comma_collist)
    2531                 :          56 :                     appendStringInfoString(&collist, ", ");
    2532                 :             :                 else
    2533                 :          40 :                     write_comma_collist = true;
    2534                 :             : 
    2535                 :          96 :                 appendStringInfoString(&collist, NameStr(att->attname));
    2536                 :             :             }
    2537                 :             :         }
    2538                 :             : 
    2539   [ +  +  +  + ]:        2732 :         if (table_perm || column_perm)
    2540                 :             :         {
    2541         [ +  + ]:        2672 :             if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
    2542                 :          40 :                 val = "virtual";
    2543         [ +  + ]:        2632 :             else if (slot->tts_isnull[i])
    2544                 :         440 :                 val = "null";
    2545                 :             :             else
    2546                 :             :             {
    2547                 :             :                 Oid         foutoid;
    2548                 :             :                 bool        typisvarlena;
    2549                 :             : 
    2550                 :        2192 :                 getTypeOutputInfo(att->atttypid,
    2551                 :             :                                   &foutoid, &typisvarlena);
    2552                 :        2192 :                 val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
    2553                 :             :             }
    2554                 :             : 
    2555         [ +  + ]:        2672 :             if (write_comma)
    2556                 :        1613 :                 appendStringInfoString(&buf, ", ");
    2557                 :             :             else
    2558                 :        1059 :                 write_comma = true;
    2559                 :             : 
    2560                 :             :             /* truncate if needed */
    2561                 :        2672 :             vallen = strlen(val);
    2562         [ +  + ]:        2672 :             if (vallen <= maxfieldlen)
    2563                 :        2663 :                 appendBinaryStringInfo(&buf, val, vallen);
    2564                 :             :             else
    2565                 :             :             {
    2566                 :           9 :                 vallen = pg_mbcliplen(val, vallen, maxfieldlen);
    2567                 :           9 :                 appendBinaryStringInfo(&buf, val, vallen);
    2568                 :           9 :                 appendStringInfoString(&buf, "...");
    2569                 :             :             }
    2570                 :             :         }
    2571                 :             :     }
    2572                 :             : 
    2573                 :             :     /* If we end up with zero columns being returned, then return NULL. */
    2574         [ -  + ]:        1059 :     if (!any_perm)
    2575                 :           0 :         return NULL;
    2576                 :             : 
    2577                 :        1059 :     appendStringInfoChar(&buf, ')');
    2578                 :             : 
    2579         [ +  + ]:        1059 :     if (!table_perm)
    2580                 :             :     {
    2581                 :          40 :         appendStringInfoString(&collist, ") = ");
    2582                 :          40 :         appendBinaryStringInfo(&collist, buf.data, buf.len);
    2583                 :             : 
    2584                 :          40 :         return collist.data;
    2585                 :             :     }
    2586                 :             : 
    2587                 :        1019 :     return buf.data;
    2588                 :             : }
    2589                 :             : 
    2590                 :             : 
    2591                 :             : /*
    2592                 :             :  * ExecUpdateLockMode -- find the appropriate UPDATE tuple lock mode for a
    2593                 :             :  * given ResultRelInfo
    2594                 :             :  */
    2595                 :             : LockTupleMode
    2596                 :        4375 : ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
    2597                 :             : {
    2598                 :             :     Bitmapset  *keyCols;
    2599                 :             :     Bitmapset  *updatedCols;
    2600                 :             : 
    2601                 :             :     /*
    2602                 :             :      * Compute lock mode to use.  If columns that are part of the key have not
    2603                 :             :      * been modified, then we can use a weaker lock, allowing for better
    2604                 :             :      * concurrency.
    2605                 :             :      */
    2606                 :        4375 :     updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
    2607                 :        4375 :     keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
    2608                 :             :                                          INDEX_ATTR_BITMAP_KEY);
    2609                 :             : 
    2610         [ +  + ]:        4375 :     if (bms_overlap(keyCols, updatedCols))
    2611                 :         179 :         return LockTupleExclusive;
    2612                 :             : 
    2613                 :        4196 :     return LockTupleNoKeyExclusive;
    2614                 :             : }
    2615                 :             : 
    2616                 :             : /*
    2617                 :             :  * ExecFindRowMark -- find the ExecRowMark struct for given rangetable index
    2618                 :             :  *
    2619                 :             :  * If no such struct, either return NULL or throw error depending on missing_ok
    2620                 :             :  */
    2621                 :             : ExecRowMark *
    2622                 :        8258 : ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
    2623                 :             : {
    2624   [ +  -  +  - ]:        8258 :     if (rti > 0 && rti <= estate->es_range_table_size &&
    2625         [ +  - ]:        8258 :         estate->es_rowmarks != NULL)
    2626                 :             :     {
    2627                 :        8258 :         ExecRowMark *erm = estate->es_rowmarks[rti - 1];
    2628                 :             : 
    2629         [ +  - ]:        8258 :         if (erm)
    2630                 :        8258 :             return erm;
    2631                 :             :     }
    2632         [ #  # ]:           0 :     if (!missing_ok)
    2633         [ #  # ]:           0 :         elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
    2634                 :           0 :     return NULL;
    2635                 :             : }
    2636                 :             : 
    2637                 :             : /*
    2638                 :             :  * ExecBuildAuxRowMark -- create an ExecAuxRowMark struct
    2639                 :             :  *
    2640                 :             :  * Inputs are the underlying ExecRowMark struct and the targetlist of the
    2641                 :             :  * input plan node (not planstate node!).  We need the latter to find out
    2642                 :             :  * the column numbers of the resjunk columns.
    2643                 :             :  */
    2644                 :             : ExecAuxRowMark *
    2645                 :        8258 : ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
    2646                 :             : {
    2647                 :        8258 :     ExecAuxRowMark *aerm = palloc0_object(ExecAuxRowMark);
    2648                 :             :     char        resname[32];
    2649                 :             : 
    2650                 :        8258 :     aerm->rowmark = erm;
    2651                 :             : 
    2652                 :             :     /* Look up the resjunk columns associated with this rowmark */
    2653         [ +  + ]:        8258 :     if (erm->markType != ROW_MARK_COPY)
    2654                 :             :     {
    2655                 :             :         /* need ctid for all methods other than COPY */
    2656                 :        7791 :         snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
    2657                 :        7791 :         aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
    2658                 :             :                                                        resname);
    2659         [ -  + ]:        7791 :         if (!AttributeNumberIsValid(aerm->ctidAttNo))
    2660         [ #  # ]:           0 :             elog(ERROR, "could not find junk %s column", resname);
    2661                 :             :     }
    2662                 :             :     else
    2663                 :             :     {
    2664                 :             :         /* need wholerow if COPY */
    2665                 :         467 :         snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
    2666                 :         467 :         aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
    2667                 :             :                                                         resname);
    2668         [ -  + ]:         467 :         if (!AttributeNumberIsValid(aerm->wholeAttNo))
    2669         [ #  # ]:           0 :             elog(ERROR, "could not find junk %s column", resname);
    2670                 :             :     }
    2671                 :             : 
    2672                 :             :     /* if child rel, need tableoid */
    2673         [ +  + ]:        8258 :     if (erm->rti != erm->prti)
    2674                 :             :     {
    2675                 :        1308 :         snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
    2676                 :        1308 :         aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
    2677                 :             :                                                        resname);
    2678         [ -  + ]:        1308 :         if (!AttributeNumberIsValid(aerm->toidAttNo))
    2679         [ #  # ]:           0 :             elog(ERROR, "could not find junk %s column", resname);
    2680                 :             :     }
    2681                 :             : 
    2682                 :        8258 :     return aerm;
    2683                 :             : }
    2684                 :             : 
    2685                 :             : 
    2686                 :             : /*
    2687                 :             :  * EvalPlanQual logic --- recheck modified tuple(s) to see if we want to
    2688                 :             :  * process the updated version under READ COMMITTED rules.
    2689                 :             :  *
    2690                 :             :  * See backend/executor/README for some info about how this works.
    2691                 :             :  */
    2692                 :             : 
    2693                 :             : 
    2694                 :             : /*
    2695                 :             :  * Check the updated version of a tuple to see if we want to process it under
    2696                 :             :  * READ COMMITTED rules.
    2697                 :             :  *
    2698                 :             :  *  epqstate - state for EvalPlanQual rechecking
    2699                 :             :  *  relation - table containing tuple
    2700                 :             :  *  rti - rangetable index of table containing tuple
    2701                 :             :  *  inputslot - tuple for processing - this can be the slot from
    2702                 :             :  *      EvalPlanQualSlot() for this rel, for increased efficiency.
    2703                 :             :  *
    2704                 :             :  * This tests whether the tuple in inputslot still matches the relevant
    2705                 :             :  * quals. For that result to be useful, typically the input tuple has to be
    2706                 :             :  * last row version (otherwise the result isn't particularly useful) and
    2707                 :             :  * locked (otherwise the result might be out of date). That's typically
    2708                 :             :  * achieved by using table_tuple_lock() with the
    2709                 :             :  * TUPLE_LOCK_FLAG_FIND_LAST_VERSION flag.
    2710                 :             :  *
    2711                 :             :  * Returns a slot containing the new candidate update/delete tuple, or
    2712                 :             :  * NULL if we determine we shouldn't process the row.
    2713                 :             :  */
    2714                 :             : TupleTableSlot *
    2715                 :         151 : EvalPlanQual(EPQState *epqstate, Relation relation,
    2716                 :             :              Index rti, TupleTableSlot *inputslot)
    2717                 :             : {
    2718                 :             :     TupleTableSlot *slot;
    2719                 :             :     TupleTableSlot *testslot;
    2720                 :             : 
    2721                 :             :     Assert(rti > 0);
    2722                 :             : 
    2723                 :             :     /*
    2724                 :             :      * Need to run a recheck subquery.  Initialize or reinitialize EPQ state.
    2725                 :             :      */
    2726                 :         151 :     EvalPlanQualBegin(epqstate);
    2727                 :             : 
    2728                 :             :     /*
    2729                 :             :      * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
    2730                 :             :      * an unnecessary copy.
    2731                 :             :      */
    2732                 :         151 :     testslot = EvalPlanQualSlot(epqstate, relation, rti);
    2733         [ +  + ]:         151 :     if (testslot != inputslot)
    2734                 :           6 :         ExecCopySlot(testslot, inputslot);
    2735                 :             : 
    2736                 :             :     /*
    2737                 :             :      * Mark that an EPQ tuple is available for this relation.  (If there is
    2738                 :             :      * more than one result relation, the others remain marked as having no
    2739                 :             :      * tuple available.)
    2740                 :             :      */
    2741                 :         151 :     epqstate->relsubs_done[rti - 1] = false;
    2742                 :         151 :     epqstate->relsubs_blocked[rti - 1] = false;
    2743                 :             : 
    2744                 :             :     /*
    2745                 :             :      * Run the EPQ query.  We assume it will return at most one tuple.
    2746                 :             :      */
    2747                 :         151 :     slot = EvalPlanQualNext(epqstate);
    2748                 :             : 
    2749                 :             :     /*
    2750                 :             :      * If we got a tuple, force the slot to materialize the tuple so that it
    2751                 :             :      * is not dependent on any local state in the EPQ query (in particular,
    2752                 :             :      * it's highly likely that the slot contains references to any pass-by-ref
    2753                 :             :      * datums that may be present in copyTuple).  As with the next step, this
    2754                 :             :      * is to guard against early re-use of the EPQ query.
    2755                 :             :      */
    2756   [ +  +  +  + ]:         151 :     if (!TupIsNull(slot))
    2757                 :         113 :         ExecMaterializeSlot(slot);
    2758                 :             : 
    2759                 :             :     /*
    2760                 :             :      * Clear out the test tuple, and mark that no tuple is available here.
    2761                 :             :      * This is needed in case the EPQ state is re-used to test a tuple for a
    2762                 :             :      * different target relation.
    2763                 :             :      */
    2764                 :         151 :     ExecClearTuple(testslot);
    2765                 :         151 :     epqstate->relsubs_blocked[rti - 1] = true;
    2766                 :             : 
    2767                 :         151 :     return slot;
    2768                 :             : }
    2769                 :             : 
    2770                 :             : /*
    2771                 :             :  * EvalPlanQualInit -- initialize during creation of a plan state node
    2772                 :             :  * that might need to invoke EPQ processing.
    2773                 :             :  *
    2774                 :             :  * If the caller intends to use EvalPlanQual(), resultRelations should be
    2775                 :             :  * a list of RT indexes of potential target relations for EvalPlanQual(),
    2776                 :             :  * and we will arrange that the other listed relations don't return any
    2777                 :             :  * tuple during an EvalPlanQual() call.  Otherwise resultRelations
    2778                 :             :  * should be NIL.
    2779                 :             :  *
    2780                 :             :  * Note: subplan/auxrowmarks can be NULL/NIL if they will be set later
    2781                 :             :  * with EvalPlanQualSetPlan.
    2782                 :             :  */
    2783                 :             : void
    2784                 :      151624 : EvalPlanQualInit(EPQState *epqstate, EState *parentestate,
    2785                 :             :                  Plan *subplan, List *auxrowmarks,
    2786                 :             :                  int epqParam, List *resultRelations)
    2787                 :             : {
    2788                 :      151624 :     Index       rtsize = parentestate->es_range_table_size;
    2789                 :             : 
    2790                 :             :     /* initialize data not changing over EPQState's lifetime */
    2791                 :      151624 :     epqstate->parentestate = parentestate;
    2792                 :      151624 :     epqstate->epqParam = epqParam;
    2793                 :      151624 :     epqstate->resultRelations = resultRelations;
    2794                 :             : 
    2795                 :             :     /*
    2796                 :             :      * Allocate space to reference a slot for each potential rti - do so now
    2797                 :             :      * rather than in EvalPlanQualBegin(), as done for other dynamically
    2798                 :             :      * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
    2799                 :             :      * that *may* need EPQ later, without forcing the overhead of
    2800                 :             :      * EvalPlanQualBegin().
    2801                 :             :      */
    2802                 :      151624 :     epqstate->tuple_table = NIL;
    2803                 :      151624 :     epqstate->relsubs_slot = palloc0_array(TupleTableSlot *, rtsize);
    2804                 :             : 
    2805                 :             :     /* ... and remember data that EvalPlanQualBegin will need */
    2806                 :      151624 :     epqstate->plan = subplan;
    2807                 :      151624 :     epqstate->arowMarks = auxrowmarks;
    2808                 :             : 
    2809                 :             :     /* ... and mark the EPQ state inactive */
    2810                 :      151624 :     epqstate->origslot = NULL;
    2811                 :      151624 :     epqstate->recheckestate = NULL;
    2812                 :      151624 :     epqstate->recheckplanstate = NULL;
    2813                 :      151624 :     epqstate->relsubs_rowmark = NULL;
    2814                 :      151624 :     epqstate->relsubs_done = NULL;
    2815                 :      151624 :     epqstate->relsubs_blocked = NULL;
    2816                 :      151624 : }
    2817                 :             : 
    2818                 :             : /*
    2819                 :             :  * EvalPlanQualSetPlan -- set or change subplan of an EPQState.
    2820                 :             :  *
    2821                 :             :  * We used to need this so that ModifyTable could deal with multiple subplans.
    2822                 :             :  * It could now be refactored out of existence.
    2823                 :             :  */
    2824                 :             : void
    2825                 :       72941 : EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
    2826                 :             : {
    2827                 :             :     /* If we have a live EPQ query, shut it down */
    2828                 :       72941 :     EvalPlanQualEnd(epqstate);
    2829                 :             :     /* And set/change the plan pointer */
    2830                 :       72941 :     epqstate->plan = subplan;
    2831                 :             :     /* The rowmarks depend on the plan, too */
    2832                 :       72941 :     epqstate->arowMarks = auxrowmarks;
    2833                 :       72941 : }
    2834                 :             : 
    2835                 :             : /*
    2836                 :             :  * Return, and create if necessary, a slot for an EPQ test tuple.
    2837                 :             :  *
    2838                 :             :  * Note this only requires EvalPlanQualInit() to have been called,
    2839                 :             :  * EvalPlanQualBegin() is not necessary.
    2840                 :             :  */
    2841                 :             : TupleTableSlot *
    2842                 :       81509 : EvalPlanQualSlot(EPQState *epqstate,
    2843                 :             :                  Relation relation, Index rti)
    2844                 :             : {
    2845                 :             :     TupleTableSlot **slot;
    2846                 :             : 
    2847                 :             :     Assert(relation);
    2848                 :             :     Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
    2849                 :       81509 :     slot = &epqstate->relsubs_slot[rti - 1];
    2850                 :             : 
    2851         [ +  + ]:       81509 :     if (*slot == NULL)
    2852                 :             :     {
    2853                 :             :         MemoryContext oldcontext;
    2854                 :             : 
    2855                 :        4967 :         oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
    2856                 :        4967 :         *slot = table_slot_create(relation, &epqstate->tuple_table);
    2857                 :        4967 :         MemoryContextSwitchTo(oldcontext);
    2858                 :             :     }
    2859                 :             : 
    2860                 :       81509 :     return *slot;
    2861                 :             : }
    2862                 :             : 
    2863                 :             : /*
    2864                 :             :  * Fetch the current row value for a non-locked relation, identified by rti,
    2865                 :             :  * that needs to be scanned by an EvalPlanQual operation.  origslot must have
    2866                 :             :  * been set to contain the current result row (top-level row) that we need to
    2867                 :             :  * recheck.  Returns true if a substitution tuple was found, false if not.
    2868                 :             :  */
    2869                 :             : bool
    2870                 :          22 : EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot)
    2871                 :             : {
    2872                 :          22 :     ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1];
    2873                 :             :     ExecRowMark *erm;
    2874                 :             :     Datum       datum;
    2875                 :             :     bool        isNull;
    2876                 :             : 
    2877                 :             :     Assert(earm != NULL);
    2878                 :             :     Assert(epqstate->origslot != NULL);
    2879                 :             : 
    2880                 :          22 :     erm = earm->rowmark;
    2881                 :             : 
    2882         [ -  + ]:          22 :     if (RowMarkRequiresRowShareLock(erm->markType))
    2883         [ #  # ]:           0 :         elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
    2884                 :             : 
    2885                 :             :     /* if child rel, must check whether it produced this row */
    2886         [ -  + ]:          22 :     if (erm->rti != erm->prti)
    2887                 :             :     {
    2888                 :             :         Oid         tableoid;
    2889                 :             : 
    2890                 :           0 :         datum = ExecGetJunkAttribute(epqstate->origslot,
    2891                 :           0 :                                      earm->toidAttNo,
    2892                 :             :                                      &isNull);
    2893                 :             :         /* non-locked rels could be on the inside of outer joins */
    2894         [ #  # ]:           0 :         if (isNull)
    2895                 :           0 :             return false;
    2896                 :             : 
    2897                 :           0 :         tableoid = DatumGetObjectId(datum);
    2898                 :             : 
    2899                 :             :         Assert(OidIsValid(erm->relid));
    2900         [ #  # ]:           0 :         if (tableoid != erm->relid)
    2901                 :             :         {
    2902                 :             :             /* this child is inactive right now */
    2903                 :           0 :             return false;
    2904                 :             :         }
    2905                 :             :     }
    2906                 :             : 
    2907         [ +  + ]:          22 :     if (erm->markType == ROW_MARK_REFERENCE)
    2908                 :             :     {
    2909                 :             :         Assert(erm->relation != NULL);
    2910                 :             : 
    2911                 :             :         /* fetch the tuple's ctid */
    2912                 :          13 :         datum = ExecGetJunkAttribute(epqstate->origslot,
    2913                 :          13 :                                      earm->ctidAttNo,
    2914                 :             :                                      &isNull);
    2915                 :             :         /* non-locked rels could be on the inside of outer joins */
    2916         [ -  + ]:          13 :         if (isNull)
    2917                 :           0 :             return false;
    2918                 :             : 
    2919                 :             :         /* fetch requests on foreign tables must be passed to their FDW */
    2920         [ -  + ]:          13 :         if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
    2921                 :             :         {
    2922                 :             :             FdwRoutine *fdwroutine;
    2923                 :           0 :             bool        updated = false;
    2924                 :             : 
    2925                 :           0 :             fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
    2926                 :             :             /* this should have been checked already, but let's be safe */
    2927         [ #  # ]:           0 :             if (fdwroutine->RefetchForeignRow == NULL)
    2928         [ #  # ]:           0 :                 ereport(ERROR,
    2929                 :             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2930                 :             :                          errmsg("cannot lock rows in foreign table \"%s\"",
    2931                 :             :                                 RelationGetRelationName(erm->relation))));
    2932                 :             : 
    2933                 :           0 :             fdwroutine->RefetchForeignRow(epqstate->recheckestate,
    2934                 :             :                                           erm,
    2935                 :             :                                           datum,
    2936                 :             :                                           slot,
    2937                 :             :                                           &updated);
    2938   [ #  #  #  # ]:           0 :             if (TupIsNull(slot))
    2939         [ #  # ]:           0 :                 elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
    2940                 :             : 
    2941                 :             :             /*
    2942                 :             :              * Ideally we'd insist on updated == false here, but that assumes
    2943                 :             :              * that FDWs can track that exactly, which they might not be able
    2944                 :             :              * to.  So just ignore the flag.
    2945                 :             :              */
    2946                 :           0 :             return true;
    2947                 :             :         }
    2948                 :             :         else
    2949                 :             :         {
    2950                 :             :             /* ordinary table, fetch the tuple */
    2951         [ -  + ]:          13 :             if (!table_tuple_fetch_row_version(erm->relation,
    2952                 :          13 :                                                (ItemPointer) DatumGetPointer(datum),
    2953                 :             :                                                SnapshotAny, slot))
    2954         [ #  # ]:           0 :                 elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
    2955                 :          13 :             return true;
    2956                 :             :         }
    2957                 :             :     }
    2958                 :             :     else
    2959                 :             :     {
    2960                 :             :         Assert(erm->markType == ROW_MARK_COPY);
    2961                 :             : 
    2962                 :             :         /* fetch the whole-row Var for the relation */
    2963                 :           9 :         datum = ExecGetJunkAttribute(epqstate->origslot,
    2964                 :           9 :                                      earm->wholeAttNo,
    2965                 :             :                                      &isNull);
    2966                 :             :         /* non-locked rels could be on the inside of outer joins */
    2967         [ -  + ]:           9 :         if (isNull)
    2968                 :           0 :             return false;
    2969                 :             : 
    2970                 :           9 :         ExecStoreHeapTupleDatum(datum, slot);
    2971                 :           9 :         return true;
    2972                 :             :     }
    2973                 :             : }
    2974                 :             : 
    2975                 :             : /*
    2976                 :             :  * Fetch the next row (if any) from EvalPlanQual testing
    2977                 :             :  *
    2978                 :             :  * (In practice, there should never be more than one row...)
    2979                 :             :  */
    2980                 :             : TupleTableSlot *
    2981                 :         191 : EvalPlanQualNext(EPQState *epqstate)
    2982                 :             : {
    2983                 :             :     MemoryContext oldcontext;
    2984                 :             :     TupleTableSlot *slot;
    2985                 :             : 
    2986                 :         191 :     oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
    2987                 :         191 :     slot = ExecProcNode(epqstate->recheckplanstate);
    2988                 :         191 :     MemoryContextSwitchTo(oldcontext);
    2989                 :             : 
    2990                 :         191 :     return slot;
    2991                 :             : }
    2992                 :             : 
    2993                 :             : /*
    2994                 :             :  * Initialize or reset an EvalPlanQual state tree
    2995                 :             :  */
    2996                 :             : void
    2997                 :         228 : EvalPlanQualBegin(EPQState *epqstate)
    2998                 :             : {
    2999                 :         228 :     EState     *parentestate = epqstate->parentestate;
    3000                 :         228 :     EState     *recheckestate = epqstate->recheckestate;
    3001                 :             : 
    3002         [ +  + ]:         228 :     if (recheckestate == NULL)
    3003                 :             :     {
    3004                 :             :         /* First time through, so create a child EState */
    3005                 :         146 :         EvalPlanQualStart(epqstate, epqstate->plan);
    3006                 :             :     }
    3007                 :             :     else
    3008                 :             :     {
    3009                 :             :         /*
    3010                 :             :          * We already have a suitable child EPQ tree, so just reset it.
    3011                 :             :          */
    3012                 :          82 :         Index       rtsize = parentestate->es_range_table_size;
    3013                 :          82 :         PlanState  *rcplanstate = epqstate->recheckplanstate;
    3014                 :             : 
    3015                 :             :         /*
    3016                 :             :          * Reset the relsubs_done[] flags to equal relsubs_blocked[], so that
    3017                 :             :          * the EPQ run will never attempt to fetch tuples from blocked target
    3018                 :             :          * relations.
    3019                 :             :          */
    3020                 :          82 :         memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
    3021                 :             :                rtsize * sizeof(bool));
    3022                 :             : 
    3023                 :             :         /* Recopy current values of parent parameters */
    3024         [ +  - ]:          82 :         if (parentestate->es_plannedstmt->paramExecTypes != NIL)
    3025                 :             :         {
    3026                 :             :             int         i;
    3027                 :             : 
    3028                 :             :             /*
    3029                 :             :              * Force evaluation of any InitPlan outputs that could be needed
    3030                 :             :              * by the subplan, just in case they got reset since
    3031                 :             :              * EvalPlanQualStart (see comments therein).
    3032                 :             :              */
    3033                 :          82 :             ExecSetParamPlanMulti(rcplanstate->plan->extParam,
    3034         [ +  - ]:          82 :                                   GetPerTupleExprContext(parentestate));
    3035                 :             : 
    3036                 :          82 :             i = list_length(parentestate->es_plannedstmt->paramExecTypes);
    3037                 :             : 
    3038         [ +  + ]:         175 :             while (--i >= 0)
    3039                 :             :             {
    3040                 :             :                 /* copy value if any, but not execPlan link */
    3041                 :          93 :                 recheckestate->es_param_exec_vals[i].value =
    3042                 :          93 :                     parentestate->es_param_exec_vals[i].value;
    3043                 :          93 :                 recheckestate->es_param_exec_vals[i].isnull =
    3044                 :          93 :                     parentestate->es_param_exec_vals[i].isnull;
    3045                 :             :             }
    3046                 :             :         }
    3047                 :             : 
    3048                 :             :         /*
    3049                 :             :          * Mark child plan tree as needing rescan at all scan nodes.  The
    3050                 :             :          * first ExecProcNode will take care of actually doing the rescan.
    3051                 :             :          */
    3052                 :          82 :         rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
    3053                 :             :                                                epqstate->epqParam);
    3054                 :             :     }
    3055                 :         228 : }
    3056                 :             : 
    3057                 :             : /*
    3058                 :             :  * Start execution of an EvalPlanQual plan tree.
    3059                 :             :  *
    3060                 :             :  * This is a cut-down version of ExecutorStart(): we copy some state from
    3061                 :             :  * the top-level estate rather than initializing it fresh.
    3062                 :             :  */
    3063                 :             : static void
    3064                 :         146 : EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
    3065                 :             : {
    3066                 :         146 :     EState     *parentestate = epqstate->parentestate;
    3067                 :         146 :     Index       rtsize = parentestate->es_range_table_size;
    3068                 :             :     EState     *rcestate;
    3069                 :             :     MemoryContext oldcontext;
    3070                 :             :     ListCell   *l;
    3071                 :             : 
    3072                 :         146 :     epqstate->recheckestate = rcestate = CreateExecutorState();
    3073                 :             : 
    3074                 :         146 :     oldcontext = MemoryContextSwitchTo(rcestate->es_query_cxt);
    3075                 :             : 
    3076                 :             :     /* signal that this is an EState for executing EPQ */
    3077                 :         146 :     rcestate->es_epq_active = epqstate;
    3078                 :             : 
    3079                 :             :     /*
    3080                 :             :      * Child EPQ EStates share the parent's copy of unchanging state such as
    3081                 :             :      * the snapshot, rangetable, and external Param info.  They need their own
    3082                 :             :      * copies of local state, including a tuple table, es_param_exec_vals,
    3083                 :             :      * result-rel info, etc.
    3084                 :             :      */
    3085                 :         146 :     rcestate->es_direction = ForwardScanDirection;
    3086                 :         146 :     rcestate->es_snapshot = parentestate->es_snapshot;
    3087                 :         146 :     rcestate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
    3088                 :         146 :     rcestate->es_range_table = parentestate->es_range_table;
    3089                 :         146 :     rcestate->es_range_table_size = parentestate->es_range_table_size;
    3090                 :         146 :     rcestate->es_relations = parentestate->es_relations;
    3091                 :         146 :     rcestate->es_rowmarks = parentestate->es_rowmarks;
    3092                 :         146 :     rcestate->es_rteperminfos = parentestate->es_rteperminfos;
    3093                 :         146 :     rcestate->es_plannedstmt = parentestate->es_plannedstmt;
    3094                 :         146 :     rcestate->es_junkFilter = parentestate->es_junkFilter;
    3095                 :         146 :     rcestate->es_output_cid = parentestate->es_output_cid;
    3096                 :         146 :     rcestate->es_queryEnv = parentestate->es_queryEnv;
    3097                 :             : 
    3098                 :             :     /*
    3099                 :             :      * ResultRelInfos needed by subplans are initialized from scratch when the
    3100                 :             :      * subplans themselves are initialized.
    3101                 :             :      */
    3102                 :         146 :     rcestate->es_result_relations = NULL;
    3103                 :             :     /* es_trig_target_relations must NOT be copied */
    3104                 :         146 :     rcestate->es_top_eflags = parentestate->es_top_eflags;
    3105                 :         146 :     rcestate->es_instrument = parentestate->es_instrument;
    3106                 :             :     /* es_auxmodifytables must NOT be copied */
    3107                 :             : 
    3108                 :             :     /*
    3109                 :             :      * The external param list is simply shared from parent.  The internal
    3110                 :             :      * param workspace has to be local state, but we copy the initial values
    3111                 :             :      * from the parent, so as to have access to any param values that were
    3112                 :             :      * already set from other parts of the parent's plan tree.
    3113                 :             :      */
    3114                 :         146 :     rcestate->es_param_list_info = parentestate->es_param_list_info;
    3115         [ +  - ]:         146 :     if (parentestate->es_plannedstmt->paramExecTypes != NIL)
    3116                 :             :     {
    3117                 :             :         int         i;
    3118                 :             : 
    3119                 :             :         /*
    3120                 :             :          * Force evaluation of any InitPlan outputs that could be needed by
    3121                 :             :          * the subplan.  (With more complexity, maybe we could postpone this
    3122                 :             :          * till the subplan actually demands them, but it doesn't seem worth
    3123                 :             :          * the trouble; this is a corner case already, since usually the
    3124                 :             :          * InitPlans would have been evaluated before reaching EvalPlanQual.)
    3125                 :             :          *
    3126                 :             :          * This will not touch output params of InitPlans that occur somewhere
    3127                 :             :          * within the subplan tree, only those that are attached to the
    3128                 :             :          * ModifyTable node or above it and are referenced within the subplan.
    3129                 :             :          * That's OK though, because the planner would only attach such
    3130                 :             :          * InitPlans to a lower-level SubqueryScan node, and EPQ execution
    3131                 :             :          * will not descend into a SubqueryScan.
    3132                 :             :          *
    3133                 :             :          * The EState's per-output-tuple econtext is sufficiently short-lived
    3134                 :             :          * for this, since it should get reset before there is any chance of
    3135                 :             :          * doing EvalPlanQual again.
    3136                 :             :          */
    3137                 :         146 :         ExecSetParamPlanMulti(planTree->extParam,
    3138         [ +  + ]:         146 :                               GetPerTupleExprContext(parentestate));
    3139                 :             : 
    3140                 :             :         /* now make the internal param workspace ... */
    3141                 :         146 :         i = list_length(parentestate->es_plannedstmt->paramExecTypes);
    3142                 :         146 :         rcestate->es_param_exec_vals = palloc0_array(ParamExecData, i);
    3143                 :             :         /* ... and copy down all values, whether really needed or not */
    3144         [ +  + ]:         347 :         while (--i >= 0)
    3145                 :             :         {
    3146                 :             :             /* copy value if any, but not execPlan link */
    3147                 :         201 :             rcestate->es_param_exec_vals[i].value =
    3148                 :         201 :                 parentestate->es_param_exec_vals[i].value;
    3149                 :         201 :             rcestate->es_param_exec_vals[i].isnull =
    3150                 :         201 :                 parentestate->es_param_exec_vals[i].isnull;
    3151                 :             :         }
    3152                 :             :     }
    3153                 :             : 
    3154                 :             :     /*
    3155                 :             :      * Copy es_unpruned_relids so that pruned relations are ignored by
    3156                 :             :      * ExecInitLockRows() and ExecInitModifyTable() when initializing the plan
    3157                 :             :      * trees below.
    3158                 :             :      */
    3159                 :         146 :     rcestate->es_unpruned_relids = parentestate->es_unpruned_relids;
    3160                 :             : 
    3161                 :             :     /*
    3162                 :             :      * Also make the PartitionPruneInfo and the results of pruning available.
    3163                 :             :      * These need to match exactly so that we initialize all the same Append
    3164                 :             :      * and MergeAppend subplans as the parent did.
    3165                 :             :      */
    3166                 :         146 :     rcestate->es_part_prune_infos = parentestate->es_part_prune_infos;
    3167                 :         146 :     rcestate->es_part_prune_states = parentestate->es_part_prune_states;
    3168                 :         146 :     rcestate->es_part_prune_results = parentestate->es_part_prune_results;
    3169                 :             : 
    3170                 :             :     /* We'll also borrow the es_partition_directory from the parent state */
    3171                 :         146 :     rcestate->es_partition_directory = parentestate->es_partition_directory;
    3172                 :             : 
    3173                 :             :     /*
    3174                 :             :      * Initialize private state information for each SubPlan.  We must do this
    3175                 :             :      * before running ExecInitNode on the main query tree, since
    3176                 :             :      * ExecInitSubPlan expects to be able to find these entries. Some of the
    3177                 :             :      * SubPlans might not be used in the part of the plan tree we intend to
    3178                 :             :      * run, but since it's not easy to tell which, we just initialize them
    3179                 :             :      * all.
    3180                 :             :      */
    3181                 :             :     Assert(rcestate->es_subplanstates == NIL);
    3182   [ +  +  +  +  :         178 :     foreach(l, parentestate->es_plannedstmt->subplans)
                   +  + ]
    3183                 :             :     {
    3184                 :          32 :         Plan       *subplan = (Plan *) lfirst(l);
    3185                 :             :         PlanState  *subplanstate;
    3186                 :             : 
    3187                 :          32 :         subplanstate = ExecInitNode(subplan, rcestate, 0);
    3188                 :          32 :         rcestate->es_subplanstates = lappend(rcestate->es_subplanstates,
    3189                 :             :                                              subplanstate);
    3190                 :             :     }
    3191                 :             : 
    3192                 :             :     /*
    3193                 :             :      * Build an RTI indexed array of rowmarks, so that
    3194                 :             :      * EvalPlanQualFetchRowMark() can efficiently access the to be fetched
    3195                 :             :      * rowmark.
    3196                 :             :      */
    3197                 :         146 :     epqstate->relsubs_rowmark = palloc0_array(ExecAuxRowMark *, rtsize);
    3198   [ +  +  +  +  :         163 :     foreach(l, epqstate->arowMarks)
                   +  + ]
    3199                 :             :     {
    3200                 :          17 :         ExecAuxRowMark *earm = (ExecAuxRowMark *) lfirst(l);
    3201                 :             : 
    3202                 :          17 :         epqstate->relsubs_rowmark[earm->rowmark->rti - 1] = earm;
    3203                 :             :     }
    3204                 :             : 
    3205                 :             :     /*
    3206                 :             :      * Initialize per-relation EPQ tuple states.  Result relations, if any,
    3207                 :             :      * get marked as blocked; others as not-fetched.
    3208                 :             :      */
    3209                 :         146 :     epqstate->relsubs_done = palloc_array(bool, rtsize);
    3210                 :         146 :     epqstate->relsubs_blocked = palloc0_array(bool, rtsize);
    3211                 :             : 
    3212   [ +  +  +  +  :         286 :     foreach(l, epqstate->resultRelations)
                   +  + ]
    3213                 :             :     {
    3214                 :         140 :         int         rtindex = lfirst_int(l);
    3215                 :             : 
    3216                 :             :         Assert(rtindex > 0 && rtindex <= rtsize);
    3217                 :         140 :         epqstate->relsubs_blocked[rtindex - 1] = true;
    3218                 :             :     }
    3219                 :             : 
    3220                 :         146 :     memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
    3221                 :             :            rtsize * sizeof(bool));
    3222                 :             : 
    3223                 :             :     /*
    3224                 :             :      * Initialize the private state information for all the nodes in the part
    3225                 :             :      * of the plan tree we need to run.  This opens files, allocates storage
    3226                 :             :      * and leaves us ready to start processing tuples.
    3227                 :             :      */
    3228                 :         146 :     epqstate->recheckplanstate = ExecInitNode(planTree, rcestate, 0);
    3229                 :             : 
    3230                 :         146 :     MemoryContextSwitchTo(oldcontext);
    3231                 :         146 : }
    3232                 :             : 
    3233                 :             : /*
    3234                 :             :  * EvalPlanQualEnd -- shut down at termination of parent plan state node,
    3235                 :             :  * or if we are done with the current EPQ child.
    3236                 :             :  *
    3237                 :             :  * This is a cut-down version of ExecutorEnd(); basically we want to do most
    3238                 :             :  * of the normal cleanup, but *not* close result relations (which we are
    3239                 :             :  * just sharing from the outer query).  We do, however, have to close any
    3240                 :             :  * result and trigger target relations that got opened, since those are not
    3241                 :             :  * shared.  (There probably shouldn't be any of the latter, but just in
    3242                 :             :  * case...)
    3243                 :             :  */
    3244                 :             : void
    3245                 :      225872 : EvalPlanQualEnd(EPQState *epqstate)
    3246                 :             : {
    3247                 :      225872 :     EState     *estate = epqstate->recheckestate;
    3248                 :             :     Index       rtsize;
    3249                 :             :     MemoryContext oldcontext;
    3250                 :             :     ListCell   *l;
    3251                 :             : 
    3252                 :      225872 :     rtsize = epqstate->parentestate->es_range_table_size;
    3253                 :             : 
    3254                 :             :     /*
    3255                 :             :      * We may have a tuple table, even if EPQ wasn't started, because we allow
    3256                 :             :      * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
    3257                 :             :      */
    3258         [ +  + ]:      225872 :     if (epqstate->tuple_table != NIL)
    3259                 :             :     {
    3260                 :        4808 :         memset(epqstate->relsubs_slot, 0,
    3261                 :             :                rtsize * sizeof(TupleTableSlot *));
    3262                 :        4808 :         ExecResetTupleTable(epqstate->tuple_table, true);
    3263                 :        4808 :         epqstate->tuple_table = NIL;
    3264                 :             :     }
    3265                 :             : 
    3266                 :             :     /* EPQ wasn't started, nothing further to do */
    3267         [ +  + ]:      225872 :     if (estate == NULL)
    3268                 :      225734 :         return;
    3269                 :             : 
    3270                 :         138 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    3271                 :             : 
    3272                 :         138 :     ExecEndNode(epqstate->recheckplanstate);
    3273                 :             : 
    3274   [ +  +  +  +  :         167 :     foreach(l, estate->es_subplanstates)
                   +  + ]
    3275                 :             :     {
    3276                 :          29 :         PlanState  *subplanstate = (PlanState *) lfirst(l);
    3277                 :             : 
    3278                 :          29 :         ExecEndNode(subplanstate);
    3279                 :             :     }
    3280                 :             : 
    3281                 :             :     /* throw away the per-estate tuple table, some node may have used it */
    3282                 :         138 :     ExecResetTupleTable(estate->es_tupleTable, false);
    3283                 :             : 
    3284                 :             :     /* Close any result and trigger target relations attached to this EState */
    3285                 :         138 :     ExecCloseResultRelations(estate);
    3286                 :             : 
    3287                 :         138 :     MemoryContextSwitchTo(oldcontext);
    3288                 :             : 
    3289                 :             :     /*
    3290                 :             :      * NULLify the partition directory before freeing the executor state.
    3291                 :             :      * Since EvalPlanQualStart() just borrowed the parent EState's directory,
    3292                 :             :      * we'd better leave it up to the parent to delete it.
    3293                 :             :      */
    3294                 :         138 :     estate->es_partition_directory = NULL;
    3295                 :             : 
    3296                 :         138 :     FreeExecutorState(estate);
    3297                 :             : 
    3298                 :             :     /* Mark EPQState idle */
    3299                 :         138 :     epqstate->origslot = NULL;
    3300                 :         138 :     epqstate->recheckestate = NULL;
    3301                 :         138 :     epqstate->recheckplanstate = NULL;
    3302                 :         138 :     epqstate->relsubs_rowmark = NULL;
    3303                 :         138 :     epqstate->relsubs_done = NULL;
    3304                 :         138 :     epqstate->relsubs_blocked = NULL;
    3305                 :             : }
        

Generated by: LCOV version 2.0-1