LCOV - code coverage report
Current view: top level - src/backend/executor - execMain.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 720 1021 70.5 %
Date: 2017-09-29 15:12:54 Functions: 37 45 82.2 %
Legend: Lines: hit not hit

          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-2017, 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/htup_details.h"
      41             : #include "access/sysattr.h"
      42             : #include "access/transam.h"
      43             : #include "access/xact.h"
      44             : #include "catalog/namespace.h"
      45             : #include "catalog/partition.h"
      46             : #include "catalog/pg_inherits_fn.h"
      47             : #include "catalog/pg_publication.h"
      48             : #include "commands/matview.h"
      49             : #include "commands/trigger.h"
      50             : #include "executor/execdebug.h"
      51             : #include "foreign/fdwapi.h"
      52             : #include "mb/pg_wchar.h"
      53             : #include "miscadmin.h"
      54             : #include "optimizer/clauses.h"
      55             : #include "parser/parsetree.h"
      56             : #include "rewrite/rewriteManip.h"
      57             : #include "storage/bufmgr.h"
      58             : #include "storage/lmgr.h"
      59             : #include "tcop/utility.h"
      60             : #include "utils/acl.h"
      61             : #include "utils/lsyscache.h"
      62             : #include "utils/memutils.h"
      63             : #include "utils/rls.h"
      64             : #include "utils/ruleutils.h"
      65             : #include "utils/snapmgr.h"
      66             : #include "utils/tqual.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 ExecCheckRTPerms() */
      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(EState *estate, PlanState *planstate,
      84             :             bool use_parallel_mode,
      85             :             CmdType operation,
      86             :             bool sendTuples,
      87             :             uint64 numberTuples,
      88             :             ScanDirection direction,
      89             :             DestReceiver *dest,
      90             :             bool execute_once);
      91             : static bool ExecCheckRTEPerms(RangeTblEntry *rte);
      92             : static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid,
      93             :                           Bitmapset *modifiedCols,
      94             :                           AclMode requiredPerms);
      95             : static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt);
      96             : static char *ExecBuildSlotValueDescription(Oid reloid,
      97             :                               TupleTableSlot *slot,
      98             :                               TupleDesc tupdesc,
      99             :                               Bitmapset *modifiedCols,
     100             :                               int maxfieldlen);
     101             : static char *ExecBuildSlotPartitionKeyDescription(Relation rel,
     102             :                                      Datum *values,
     103             :                                      bool *isnull,
     104             :                                      int maxfieldlen);
     105             : static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
     106             :                   Plan *planTree);
     107             : static void ExecPartitionCheck(ResultRelInfo *resultRelInfo,
     108             :                    TupleTableSlot *slot, EState *estate);
     109             : 
     110             : /*
     111             :  * Note that GetUpdatedColumns() also exists in commands/trigger.c.  There does
     112             :  * not appear to be any good header to put it into, given the structures that
     113             :  * it uses, so we let them be duplicated.  Be sure to update both if one needs
     114             :  * to be changed, however.
     115             :  */
     116             : #define GetInsertedColumns(relinfo, estate) \
     117             :     (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->insertedCols)
     118             : #define GetUpdatedColumns(relinfo, estate) \
     119             :     (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
     120             : 
     121             : /* end of local decls */
     122             : 
     123             : 
     124             : /* ----------------------------------------------------------------
     125             :  *      ExecutorStart
     126             :  *
     127             :  *      This routine must be called at the beginning of any execution of any
     128             :  *      query plan
     129             :  *
     130             :  * Takes a QueryDesc previously created by CreateQueryDesc (which is separate
     131             :  * only because some places use QueryDescs for utility commands).  The tupDesc
     132             :  * field of the QueryDesc is filled in to describe the tuples that will be
     133             :  * returned, and the internal fields (estate and planstate) are set up.
     134             :  *
     135             :  * eflags contains flag bits as described in executor.h.
     136             :  *
     137             :  * NB: the CurrentMemoryContext when this is called will become the parent
     138             :  * of the per-query context used for this Executor invocation.
     139             :  *
     140             :  * We provide a function hook variable that lets loadable plugins
     141             :  * get control when ExecutorStart is called.  Such a plugin would
     142             :  * normally call standard_ExecutorStart().
     143             :  *
     144             :  * ----------------------------------------------------------------
     145             :  */
     146             : void
     147       24667 : ExecutorStart(QueryDesc *queryDesc, int eflags)
     148             : {
     149       24667 :     if (ExecutorStart_hook)
     150           0 :         (*ExecutorStart_hook) (queryDesc, eflags);
     151             :     else
     152       24667 :         standard_ExecutorStart(queryDesc, eflags);
     153       24588 : }
     154             : 
     155             : void
     156       24667 : standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
     157             : {
     158             :     EState     *estate;
     159             :     MemoryContext oldcontext;
     160             : 
     161             :     /* sanity checks: queryDesc must not be started already */
     162       24667 :     Assert(queryDesc != NULL);
     163       24667 :     Assert(queryDesc->estate == NULL);
     164             : 
     165             :     /*
     166             :      * If the transaction is read-only, we need to check if any writes are
     167             :      * planned to non-temporary tables.  EXPLAIN is considered read-only.
     168             :      *
     169             :      * Don't allow writes in parallel mode.  Supporting UPDATE and DELETE
     170             :      * would require (a) storing the combocid hash in shared memory, rather
     171             :      * than synchronizing it just once at the start of parallelism, and (b) an
     172             :      * alternative to heap_update()'s reliance on xmax for mutual exclusion.
     173             :      * INSERT may have no such troubles, but we forbid it to simplify the
     174             :      * checks.
     175             :      *
     176             :      * We have lower-level defenses in CommandCounterIncrement and elsewhere
     177             :      * against performing unsafe operations in parallel mode, but this gives a
     178             :      * more user-friendly error message.
     179             :      */
     180       24798 :     if ((XactReadOnly || IsInParallelMode()) &&
     181         131 :         !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
     182         131 :         ExecCheckXactReadOnly(queryDesc->plannedstmt);
     183             : 
     184             :     /*
     185             :      * Build EState, switch into per-query memory context for startup.
     186             :      */
     187       24665 :     estate = CreateExecutorState();
     188       24665 :     queryDesc->estate = estate;
     189             : 
     190       24665 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     191             : 
     192             :     /*
     193             :      * Fill in external parameters, if any, from queryDesc; and allocate
     194             :      * workspace for internal parameters
     195             :      */
     196       24665 :     estate->es_param_list_info = queryDesc->params;
     197             : 
     198       24665 :     if (queryDesc->plannedstmt->nParamExec > 0)
     199        8132 :         estate->es_param_exec_vals = (ParamExecData *)
     200        8132 :             palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData));
     201             : 
     202       24665 :     estate->es_sourceText = queryDesc->sourceText;
     203             : 
     204             :     /*
     205             :      * Fill in the query environment, if any, from queryDesc.
     206             :      */
     207       24665 :     estate->es_queryEnv = queryDesc->queryEnv;
     208             : 
     209             :     /*
     210             :      * If non-read-only query, set the command ID to mark output tuples with
     211             :      */
     212       24665 :     switch (queryDesc->operation)
     213             :     {
     214             :         case CMD_SELECT:
     215             : 
     216             :             /*
     217             :              * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark
     218             :              * tuples
     219             :              */
     220       39989 :             if (queryDesc->plannedstmt->rowMarks != NIL ||
     221       19811 :                 queryDesc->plannedstmt->hasModifyingCTE)
     222         386 :                 estate->es_output_cid = GetCurrentCommandId(true);
     223             : 
     224             :             /*
     225             :              * A SELECT without modifying CTEs can't possibly queue triggers,
     226             :              * so force skip-triggers mode. This is just a marginal efficiency
     227             :              * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't
     228             :              * all that expensive, but we might as well do it.
     229             :              */
     230       20178 :             if (!queryDesc->plannedstmt->hasModifyingCTE)
     231       20159 :                 eflags |= EXEC_FLAG_SKIP_TRIGGERS;
     232       20178 :             break;
     233             : 
     234             :         case CMD_INSERT:
     235             :         case CMD_DELETE:
     236             :         case CMD_UPDATE:
     237        4487 :             estate->es_output_cid = GetCurrentCommandId(true);
     238        4487 :             break;
     239             : 
     240             :         default:
     241           0 :             elog(ERROR, "unrecognized operation code: %d",
     242             :                  (int) queryDesc->operation);
     243             :             break;
     244             :     }
     245             : 
     246             :     /*
     247             :      * Copy other important information into the EState
     248             :      */
     249       24665 :     estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot);
     250       24665 :     estate->es_crosscheck_snapshot = RegisterSnapshot(queryDesc->crosscheck_snapshot);
     251       24665 :     estate->es_top_eflags = eflags;
     252       24665 :     estate->es_instrument = queryDesc->instrument_options;
     253             : 
     254             :     /*
     255             :      * Initialize the plan state tree
     256             :      */
     257       24665 :     InitPlan(queryDesc, eflags);
     258             : 
     259             :     /*
     260             :      * Set up an AFTER-trigger statement context, unless told not to, or
     261             :      * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called).
     262             :      */
     263       24588 :     if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY)))
     264        4371 :         AfterTriggerBeginQuery();
     265             : 
     266       24588 :     MemoryContextSwitchTo(oldcontext);
     267       24588 : }
     268             : 
     269             : /* ----------------------------------------------------------------
     270             :  *      ExecutorRun
     271             :  *
     272             :  *      This is the main routine of the executor module. It accepts
     273             :  *      the query descriptor from the traffic cop and executes the
     274             :  *      query plan.
     275             :  *
     276             :  *      ExecutorStart must have been called already.
     277             :  *
     278             :  *      If direction is NoMovementScanDirection then nothing is done
     279             :  *      except to start up/shut down the destination.  Otherwise,
     280             :  *      we retrieve up to 'count' tuples in the specified direction.
     281             :  *
     282             :  *      Note: count = 0 is interpreted as no portal limit, i.e., run to
     283             :  *      completion.  Also note that the count limit is only applied to
     284             :  *      retrieved tuples, not for instance to those inserted/updated/deleted
     285             :  *      by a ModifyTable plan node.
     286             :  *
     287             :  *      There is no return value, but output tuples (if any) are sent to
     288             :  *      the destination receiver specified in the QueryDesc; and the number
     289             :  *      of tuples processed at the top level can be found in
     290             :  *      estate->es_processed.
     291             :  *
     292             :  *      We provide a function hook variable that lets loadable plugins
     293             :  *      get control when ExecutorRun is called.  Such a plugin would
     294             :  *      normally call standard_ExecutorRun().
     295             :  *
     296             :  * ----------------------------------------------------------------
     297             :  */
     298             : void
     299       24017 : ExecutorRun(QueryDesc *queryDesc,
     300             :             ScanDirection direction, uint64 count,
     301             :             bool execute_once)
     302             : {
     303       24017 :     if (ExecutorRun_hook)
     304           0 :         (*ExecutorRun_hook) (queryDesc, direction, count, execute_once);
     305             :     else
     306       24017 :         standard_ExecutorRun(queryDesc, direction, count, execute_once);
     307       20853 : }
     308             : 
     309             : void
     310       24017 : standard_ExecutorRun(QueryDesc *queryDesc,
     311             :                      ScanDirection direction, uint64 count, bool execute_once)
     312             : {
     313             :     EState     *estate;
     314             :     CmdType     operation;
     315             :     DestReceiver *dest;
     316             :     bool        sendTuples;
     317             :     MemoryContext oldcontext;
     318             : 
     319             :     /* sanity checks */
     320       24017 :     Assert(queryDesc != NULL);
     321             : 
     322       24017 :     estate = queryDesc->estate;
     323             : 
     324       24017 :     Assert(estate != NULL);
     325       24017 :     Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
     326             : 
     327             :     /*
     328             :      * Switch into per-query memory context
     329             :      */
     330       24017 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     331             : 
     332             :     /* Allow instrumentation of Executor overall runtime */
     333       24017 :     if (queryDesc->totaltime)
     334           0 :         InstrStartNode(queryDesc->totaltime);
     335             : 
     336             :     /*
     337             :      * extract information from the query descriptor and the query feature.
     338             :      */
     339       24017 :     operation = queryDesc->operation;
     340       24017 :     dest = queryDesc->dest;
     341             : 
     342             :     /*
     343             :      * startup tuple receiver, if we will be emitting tuples
     344             :      */
     345       24017 :     estate->es_processed = 0;
     346       24017 :     estate->es_lastoid = InvalidOid;
     347             : 
     348       28411 :     sendTuples = (operation == CMD_SELECT ||
     349        4394 :                   queryDesc->plannedstmt->hasReturning);
     350             : 
     351       24017 :     if (sendTuples)
     352       19840 :         (*dest->rStartup) (dest, operation, queryDesc->tupDesc);
     353             : 
     354             :     /*
     355             :      * run plan
     356             :      */
     357       24007 :     if (!ScanDirectionIsNoMovement(direction))
     358             :     {
     359       23779 :         if (execute_once && queryDesc->already_executed)
     360           0 :             elog(ERROR, "can't re-execute query flagged for single execution");
     361       23779 :         queryDesc->already_executed = true;
     362             : 
     363       47558 :         ExecutePlan(estate,
     364             :                     queryDesc->planstate,
     365       23779 :                     queryDesc->plannedstmt->parallelModeNeeded,
     366             :                     operation,
     367             :                     sendTuples,
     368             :                     count,
     369             :                     direction,
     370             :                     dest,
     371             :                     execute_once);
     372             :     }
     373             : 
     374             :     /*
     375             :      * shutdown tuple receiver, if we started it
     376             :      */
     377       20853 :     if (sendTuples)
     378       16920 :         (*dest->rShutdown) (dest);
     379             : 
     380       20853 :     if (queryDesc->totaltime)
     381           0 :         InstrStopNode(queryDesc->totaltime, estate->es_processed);
     382             : 
     383       20853 :     MemoryContextSwitchTo(oldcontext);
     384       20853 : }
     385             : 
     386             : /* ----------------------------------------------------------------
     387             :  *      ExecutorFinish
     388             :  *
     389             :  *      This routine must be called after the last ExecutorRun call.
     390             :  *      It performs cleanup such as firing AFTER triggers.  It is
     391             :  *      separate from ExecutorEnd because EXPLAIN ANALYZE needs to
     392             :  *      include these actions in the total runtime.
     393             :  *
     394             :  *      We provide a function hook variable that lets loadable plugins
     395             :  *      get control when ExecutorFinish is called.  Such a plugin would
     396             :  *      normally call standard_ExecutorFinish().
     397             :  *
     398             :  * ----------------------------------------------------------------
     399             :  */
     400             : void
     401       20277 : ExecutorFinish(QueryDesc *queryDesc)
     402             : {
     403       20277 :     if (ExecutorFinish_hook)
     404           0 :         (*ExecutorFinish_hook) (queryDesc);
     405             :     else
     406       20277 :         standard_ExecutorFinish(queryDesc);
     407       20209 : }
     408             : 
     409             : void
     410       20277 : standard_ExecutorFinish(QueryDesc *queryDesc)
     411             : {
     412             :     EState     *estate;
     413             :     MemoryContext oldcontext;
     414             : 
     415             :     /* sanity checks */
     416       20277 :     Assert(queryDesc != NULL);
     417             : 
     418       20277 :     estate = queryDesc->estate;
     419             : 
     420       20277 :     Assert(estate != NULL);
     421       20277 :     Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
     422             : 
     423             :     /* This should be run once and only once per Executor instance */
     424       20277 :     Assert(!estate->es_finished);
     425             : 
     426             :     /* Switch into per-query memory context */
     427       20277 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     428             : 
     429             :     /* Allow instrumentation of Executor overall runtime */
     430       20277 :     if (queryDesc->totaltime)
     431           0 :         InstrStartNode(queryDesc->totaltime);
     432             : 
     433             :     /* Run ModifyTable nodes to completion */
     434       20277 :     ExecPostprocessPlan(estate);
     435             : 
     436             :     /* Execute queued AFTER triggers, unless told not to */
     437       20277 :     if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
     438        4117 :         AfterTriggerEndQuery(estate);
     439             : 
     440       20209 :     if (queryDesc->totaltime)
     441           0 :         InstrStopNode(queryDesc->totaltime, 0);
     442             : 
     443       20209 :     MemoryContextSwitchTo(oldcontext);
     444             : 
     445       20209 :     estate->es_finished = true;
     446       20209 : }
     447             : 
     448             : /* ----------------------------------------------------------------
     449             :  *      ExecutorEnd
     450             :  *
     451             :  *      This routine must be called at the end of execution of any
     452             :  *      query plan
     453             :  *
     454             :  *      We provide a function hook variable that lets loadable plugins
     455             :  *      get control when ExecutorEnd is called.  Such a plugin would
     456             :  *      normally call standard_ExecutorEnd().
     457             :  *
     458             :  * ----------------------------------------------------------------
     459             :  */
     460             : void
     461       21321 : ExecutorEnd(QueryDesc *queryDesc)
     462             : {
     463       21321 :     if (ExecutorEnd_hook)
     464           0 :         (*ExecutorEnd_hook) (queryDesc);
     465             :     else
     466       21321 :         standard_ExecutorEnd(queryDesc);
     467       21321 : }
     468             : 
     469             : void
     470       21321 : standard_ExecutorEnd(QueryDesc *queryDesc)
     471             : {
     472             :     EState     *estate;
     473             :     MemoryContext oldcontext;
     474             : 
     475             :     /* sanity checks */
     476       21321 :     Assert(queryDesc != NULL);
     477             : 
     478       21321 :     estate = queryDesc->estate;
     479             : 
     480       21321 :     Assert(estate != NULL);
     481             : 
     482             :     /*
     483             :      * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This
     484             :      * Assert is needed because ExecutorFinish is new as of 9.1, and callers
     485             :      * might forget to call it.
     486             :      */
     487       21321 :     Assert(estate->es_finished ||
     488             :            (estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
     489             : 
     490             :     /*
     491             :      * Switch into per-query memory context to run ExecEndPlan
     492             :      */
     493       21321 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     494             : 
     495       21321 :     ExecEndPlan(queryDesc->planstate, estate);
     496             : 
     497             :     /* do away with our snapshots */
     498       21321 :     UnregisterSnapshot(estate->es_snapshot);
     499       21321 :     UnregisterSnapshot(estate->es_crosscheck_snapshot);
     500             : 
     501             :     /*
     502             :      * Must switch out of context before destroying it
     503             :      */
     504       21321 :     MemoryContextSwitchTo(oldcontext);
     505             : 
     506             :     /*
     507             :      * Release EState and per-query memory context.  This should release
     508             :      * everything the executor has allocated.
     509             :      */
     510       21321 :     FreeExecutorState(estate);
     511             : 
     512             :     /* Reset queryDesc fields that no longer point to anything */
     513       21321 :     queryDesc->tupDesc = NULL;
     514       21321 :     queryDesc->estate = NULL;
     515       21321 :     queryDesc->planstate = NULL;
     516       21321 :     queryDesc->totaltime = NULL;
     517       21321 : }
     518             : 
     519             : /* ----------------------------------------------------------------
     520             :  *      ExecutorRewind
     521             :  *
     522             :  *      This routine may be called on an open queryDesc to rewind it
     523             :  *      to the start.
     524             :  * ----------------------------------------------------------------
     525             :  */
     526             : void
     527          14 : ExecutorRewind(QueryDesc *queryDesc)
     528             : {
     529             :     EState     *estate;
     530             :     MemoryContext oldcontext;
     531             : 
     532             :     /* sanity checks */
     533          14 :     Assert(queryDesc != NULL);
     534             : 
     535          14 :     estate = queryDesc->estate;
     536             : 
     537          14 :     Assert(estate != NULL);
     538             : 
     539             :     /* It's probably not sensible to rescan updating queries */
     540          14 :     Assert(queryDesc->operation == CMD_SELECT);
     541             : 
     542             :     /*
     543             :      * Switch into per-query memory context
     544             :      */
     545          14 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
     546             : 
     547             :     /*
     548             :      * rescan plan
     549             :      */
     550          14 :     ExecReScan(queryDesc->planstate);
     551             : 
     552          14 :     MemoryContextSwitchTo(oldcontext);
     553          14 : }
     554             : 
     555             : 
     556             : /*
     557             :  * ExecCheckRTPerms
     558             :  *      Check access permissions for all relations listed in a range table.
     559             :  *
     560             :  * Returns true if permissions are adequate.  Otherwise, throws an appropriate
     561             :  * error if ereport_on_violation is true, or simply returns false otherwise.
     562             :  *
     563             :  * Note that this does NOT address row level security policies (aka: RLS).  If
     564             :  * rows will be returned to the user as a result of this permission check
     565             :  * passing, then RLS also needs to be consulted (and check_enable_rls()).
     566             :  *
     567             :  * See rewrite/rowsecurity.c.
     568             :  */
     569             : bool
     570       24965 : ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
     571             : {
     572             :     ListCell   *l;
     573       24965 :     bool        result = true;
     574             : 
     575       59802 :     foreach(l, rangeTable)
     576             :     {
     577       34924 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
     578             : 
     579       34924 :         result = ExecCheckRTEPerms(rte);
     580       34924 :         if (!result)
     581             :         {
     582          87 :             Assert(rte->rtekind == RTE_RELATION);
     583          87 :             if (ereport_on_violation)
     584          87 :                 aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
     585          87 :                                get_rel_name(rte->relid));
     586           0 :             return false;
     587             :         }
     588             :     }
     589             : 
     590       24878 :     if (ExecutorCheckPerms_hook)
     591           0 :         result = (*ExecutorCheckPerms_hook) (rangeTable,
     592             :                                              ereport_on_violation);
     593       24878 :     return result;
     594             : }
     595             : 
     596             : /*
     597             :  * ExecCheckRTEPerms
     598             :  *      Check access permissions for a single RTE.
     599             :  */
     600             : static bool
     601       34924 : ExecCheckRTEPerms(RangeTblEntry *rte)
     602             : {
     603             :     AclMode     requiredPerms;
     604             :     AclMode     relPerms;
     605             :     AclMode     remainingPerms;
     606             :     Oid         relOid;
     607             :     Oid         userid;
     608             : 
     609             :     /*
     610             :      * Only plain-relation RTEs need to be checked here.  Function RTEs are
     611             :      * checked when the function is prepared for execution.  Join, subquery,
     612             :      * and special RTEs need no checks.
     613             :      */
     614       34924 :     if (rte->rtekind != RTE_RELATION)
     615        8076 :         return true;
     616             : 
     617             :     /*
     618             :      * No work if requiredPerms is empty.
     619             :      */
     620       26848 :     requiredPerms = rte->requiredPerms;
     621       26848 :     if (requiredPerms == 0)
     622        2368 :         return true;
     623             : 
     624       24480 :     relOid = rte->relid;
     625             : 
     626             :     /*
     627             :      * userid to check as: current user unless we have a setuid indication.
     628             :      *
     629             :      * Note: GetUserId() is presently fast enough that there's no harm in
     630             :      * calling it separately for each RTE.  If that stops being true, we could
     631             :      * call it once in ExecCheckRTPerms and pass the userid down from there.
     632             :      * But for now, no need for the extra clutter.
     633             :      */
     634       24480 :     userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
     635             : 
     636             :     /*
     637             :      * We must have *all* the requiredPerms bits, but some of the bits can be
     638             :      * satisfied from column-level rather than relation-level permissions.
     639             :      * First, remove any bits that are satisfied by relation permissions.
     640             :      */
     641       24480 :     relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL);
     642       24480 :     remainingPerms = requiredPerms & ~relPerms;
     643       24480 :     if (remainingPerms != 0)
     644             :     {
     645         136 :         int         col = -1;
     646             : 
     647             :         /*
     648             :          * If we lack any permissions that exist only as relation permissions,
     649             :          * we can fail straight away.
     650             :          */
     651         136 :         if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE))
     652           8 :             return false;
     653             : 
     654             :         /*
     655             :          * Check to see if we have the needed privileges at column level.
     656             :          *
     657             :          * Note: failures just report a table-level error; it would be nicer
     658             :          * to report a column-level error if we have some but not all of the
     659             :          * column privileges.
     660             :          */
     661         128 :         if (remainingPerms & ACL_SELECT)
     662             :         {
     663             :             /*
     664             :              * When the query doesn't explicitly reference any columns (for
     665             :              * example, SELECT COUNT(*) FROM table), allow the query if we
     666             :              * have SELECT on any column of the rel, as per SQL spec.
     667             :              */
     668          86 :             if (bms_is_empty(rte->selectedCols))
     669             :             {
     670           5 :                 if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
     671             :                                               ACLMASK_ANY) != ACLCHECK_OK)
     672           1 :                     return false;
     673             :             }
     674             : 
     675         230 :             while ((col = bms_next_member(rte->selectedCols, col)) >= 0)
     676             :             {
     677             :                 /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
     678         106 :                 AttrNumber  attno = col + FirstLowInvalidHeapAttributeNumber;
     679             : 
     680         106 :                 if (attno == InvalidAttrNumber)
     681             :                 {
     682             :                     /* Whole-row reference, must have priv on all cols */
     683           7 :                     if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
     684             :                                                   ACLMASK_ALL) != ACLCHECK_OK)
     685           3 :                         return false;
     686             :                 }
     687             :                 else
     688             :                 {
     689          99 :                     if (pg_attribute_aclcheck(relOid, attno, userid,
     690             :                                               ACL_SELECT) != ACLCHECK_OK)
     691          43 :                         return false;
     692             :                 }
     693             :             }
     694             :         }
     695             : 
     696             :         /*
     697             :          * Basically the same for the mod columns, for both INSERT and UPDATE
     698             :          * privilege as specified by remainingPerms.
     699             :          */
     700          81 :         if (remainingPerms & ACL_INSERT && !ExecCheckRTEPermsModified(relOid,
     701             :                                                                       userid,
     702             :                                                                       rte->insertedCols,
     703             :                                                                       ACL_INSERT))
     704          21 :             return false;
     705             : 
     706          60 :         if (remainingPerms & ACL_UPDATE && !ExecCheckRTEPermsModified(relOid,
     707             :                                                                       userid,
     708             :                                                                       rte->updatedCols,
     709             :                                                                       ACL_UPDATE))
     710          11 :             return false;
     711             :     }
     712       24393 :     return true;
     713             : }
     714             : 
     715             : /*
     716             :  * ExecCheckRTEPermsModified
     717             :  *      Check INSERT or UPDATE access permissions for a single RTE (these
     718             :  *      are processed uniformly).
     719             :  */
     720             : static bool
     721          53 : ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols,
     722             :                           AclMode requiredPerms)
     723             : {
     724          53 :     int         col = -1;
     725             : 
     726             :     /*
     727             :      * When the query doesn't explicitly update any columns, allow the query
     728             :      * if we have permission on any column of the rel.  This is to handle
     729             :      * SELECT FOR UPDATE as well as possible corner cases in UPDATE.
     730             :      */
     731          53 :     if (bms_is_empty(modifiedCols))
     732             :     {
     733           2 :         if (pg_attribute_aclcheck_all(relOid, userid, requiredPerms,
     734             :                                       ACLMASK_ANY) != ACLCHECK_OK)
     735           2 :             return false;
     736             :     }
     737             : 
     738         128 :     while ((col = bms_next_member(modifiedCols, col)) >= 0)
     739             :     {
     740             :         /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
     741          56 :         AttrNumber  attno = col + FirstLowInvalidHeapAttributeNumber;
     742             : 
     743          56 :         if (attno == InvalidAttrNumber)
     744             :         {
     745             :             /* whole-row reference can't happen here */
     746           0 :             elog(ERROR, "whole-row update is not implemented");
     747             :         }
     748             :         else
     749             :         {
     750          56 :             if (pg_attribute_aclcheck(relOid, attno, userid,
     751             :                                       requiredPerms) != ACLCHECK_OK)
     752          30 :                 return false;
     753             :         }
     754             :     }
     755          21 :     return true;
     756             : }
     757             : 
     758             : /*
     759             :  * Check that the query does not imply any writes to non-temp tables;
     760             :  * unless we're in parallel mode, in which case don't even allow writes
     761             :  * to temp tables.
     762             :  *
     763             :  * Note: in a Hot Standby this would need to reject writes to temp
     764             :  * tables just as we do in parallel mode; but an HS standby can't have created
     765             :  * any temp tables in the first place, so no need to check that.
     766             :  */
     767             : static void
     768         131 : ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
     769             : {
     770             :     ListCell   *l;
     771             : 
     772             :     /*
     773             :      * Fail if write permissions are requested in parallel mode for table
     774             :      * (temp or non-temp), otherwise fail for any non-temp table.
     775             :      */
     776         456 :     foreach(l, plannedstmt->rtable)
     777             :     {
     778         327 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
     779             : 
     780         327 :         if (rte->rtekind != RTE_RELATION)
     781         145 :             continue;
     782             : 
     783         182 :         if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
     784         178 :             continue;
     785             : 
     786           4 :         if (isTempNamespace(get_rel_namespace(rte->relid)))
     787           2 :             continue;
     788             : 
     789           2 :         PreventCommandIfReadOnly(CreateCommandTag((Node *) plannedstmt));
     790             :     }
     791             : 
     792         129 :     if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
     793           2 :         PreventCommandIfParallelMode(CreateCommandTag((Node *) plannedstmt));
     794         129 : }
     795             : 
     796             : 
     797             : /* ----------------------------------------------------------------
     798             :  *      InitPlan
     799             :  *
     800             :  *      Initializes the query plan: open files, allocate storage
     801             :  *      and start up the rule manager
     802             :  * ----------------------------------------------------------------
     803             :  */
     804             : static void
     805       24665 : InitPlan(QueryDesc *queryDesc, int eflags)
     806             : {
     807       24665 :     CmdType     operation = queryDesc->operation;
     808       24665 :     PlannedStmt *plannedstmt = queryDesc->plannedstmt;
     809       24665 :     Plan       *plan = plannedstmt->planTree;
     810       24665 :     List       *rangeTable = plannedstmt->rtable;
     811       24665 :     EState     *estate = queryDesc->estate;
     812             :     PlanState  *planstate;
     813             :     TupleDesc   tupType;
     814             :     ListCell   *l;
     815             :     int         i;
     816             : 
     817             :     /*
     818             :      * Do permissions checks
     819             :      */
     820       24665 :     ExecCheckRTPerms(rangeTable, true);
     821             : 
     822             :     /*
     823             :      * initialize the node's execution state
     824             :      */
     825       24593 :     estate->es_range_table = rangeTable;
     826       24593 :     estate->es_plannedstmt = plannedstmt;
     827             : 
     828             :     /*
     829             :      * initialize result relation stuff, and open/lock the result rels.
     830             :      *
     831             :      * We must do this before initializing the plan tree, else we might try to
     832             :      * do a lock upgrade if a result rel is also a source rel.
     833             :      */
     834       24593 :     if (plannedstmt->resultRelations)
     835             :     {
     836        4470 :         List       *resultRelations = plannedstmt->resultRelations;
     837        4470 :         int         numResultRelations = list_length(resultRelations);
     838             :         ResultRelInfo *resultRelInfos;
     839             :         ResultRelInfo *resultRelInfo;
     840             : 
     841        4470 :         resultRelInfos = (ResultRelInfo *)
     842        4470 :             palloc(numResultRelations * sizeof(ResultRelInfo));
     843        4470 :         resultRelInfo = resultRelInfos;
     844        9070 :         foreach(l, resultRelations)
     845             :         {
     846        4600 :             Index       resultRelationIndex = lfirst_int(l);
     847             :             Oid         resultRelationOid;
     848             :             Relation    resultRelation;
     849             : 
     850        4600 :             resultRelationOid = getrelid(resultRelationIndex, rangeTable);
     851        4600 :             resultRelation = heap_open(resultRelationOid, RowExclusiveLock);
     852             : 
     853        4600 :             InitResultRelInfo(resultRelInfo,
     854             :                               resultRelation,
     855             :                               resultRelationIndex,
     856             :                               NULL,
     857             :                               estate->es_instrument);
     858        4600 :             resultRelInfo++;
     859             :         }
     860        4470 :         estate->es_result_relations = resultRelInfos;
     861        4470 :         estate->es_num_result_relations = numResultRelations;
     862             :         /* es_result_relation_info is NULL except when within ModifyTable */
     863        4470 :         estate->es_result_relation_info = NULL;
     864             : 
     865             :         /*
     866             :          * In the partitioned result relation case, lock the non-leaf result
     867             :          * relations too.  A subset of these are the roots of respective
     868             :          * partitioned tables, for which we also allocate ResulRelInfos.
     869             :          */
     870        4470 :         estate->es_root_result_relations = NULL;
     871        4470 :         estate->es_num_root_result_relations = 0;
     872        4470 :         if (plannedstmt->nonleafResultRelations)
     873             :         {
     874          10 :             int         num_roots = list_length(plannedstmt->rootResultRelations);
     875             : 
     876             :             /*
     877             :              * Firstly, build ResultRelInfos for all the partitioned table
     878             :              * roots, because we will need them to fire the statement-level
     879             :              * triggers, if any.
     880             :              */
     881          10 :             resultRelInfos = (ResultRelInfo *)
     882          10 :                 palloc(num_roots * sizeof(ResultRelInfo));
     883          10 :             resultRelInfo = resultRelInfos;
     884          21 :             foreach(l, plannedstmt->rootResultRelations)
     885             :             {
     886          11 :                 Index       resultRelIndex = lfirst_int(l);
     887             :                 Oid         resultRelOid;
     888             :                 Relation    resultRelDesc;
     889             : 
     890          11 :                 resultRelOid = getrelid(resultRelIndex, rangeTable);
     891          11 :                 resultRelDesc = heap_open(resultRelOid, RowExclusiveLock);
     892          22 :                 InitResultRelInfo(resultRelInfo,
     893             :                                   resultRelDesc,
     894          11 :                                   lfirst_int(l),
     895             :                                   NULL,
     896             :                                   estate->es_instrument);
     897          11 :                 resultRelInfo++;
     898             :             }
     899             : 
     900          10 :             estate->es_root_result_relations = resultRelInfos;
     901          10 :             estate->es_num_root_result_relations = num_roots;
     902             : 
     903             :             /* Simply lock the rest of them. */
     904          21 :             foreach(l, plannedstmt->nonleafResultRelations)
     905             :             {
     906          11 :                 Index       resultRelIndex = lfirst_int(l);
     907             : 
     908             :                 /* We locked the roots above. */
     909          11 :                 if (!list_member_int(plannedstmt->rootResultRelations,
     910             :                                      resultRelIndex))
     911           0 :                     LockRelationOid(getrelid(resultRelIndex, rangeTable),
     912             :                                     RowExclusiveLock);
     913             :             }
     914             :         }
     915             :     }
     916             :     else
     917             :     {
     918             :         /*
     919             :          * if no result relation, then set state appropriately
     920             :          */
     921       20123 :         estate->es_result_relations = NULL;
     922       20123 :         estate->es_num_result_relations = 0;
     923       20123 :         estate->es_result_relation_info = NULL;
     924       20123 :         estate->es_root_result_relations = NULL;
     925       20123 :         estate->es_num_root_result_relations = 0;
     926             :     }
     927             : 
     928             :     /*
     929             :      * Similarly, we have to lock relations selected FOR [KEY] UPDATE/SHARE
     930             :      * before we initialize the plan tree, else we'd be risking lock upgrades.
     931             :      * While we are at it, build the ExecRowMark list.  Any partitioned child
     932             :      * tables are ignored here (because isParent=true) and will be locked by
     933             :      * the first Append or MergeAppend node that references them.  (Note that
     934             :      * the RowMarks corresponding to partitioned child tables are present in
     935             :      * the same list as the rest, i.e., plannedstmt->rowMarks.)
     936             :      */
     937       24593 :     estate->es_rowMarks = NIL;
     938       25164 :     foreach(l, plannedstmt->rowMarks)
     939             :     {
     940         572 :         PlanRowMark *rc = (PlanRowMark *) lfirst(l);
     941             :         Oid         relid;
     942             :         Relation    relation;
     943             :         ExecRowMark *erm;
     944             : 
     945             :         /* ignore "parent" rowmarks; they are irrelevant at runtime */
     946         572 :         if (rc->isParent)
     947          16 :             continue;
     948             : 
     949             :         /* get relation's OID (will produce InvalidOid if subquery) */
     950         556 :         relid = getrelid(rc->rti, rangeTable);
     951             : 
     952             :         /*
     953             :          * If you change the conditions under which rel locks are acquired
     954             :          * here, be sure to adjust ExecOpenScanRelation to match.
     955             :          */
     956         556 :         switch (rc->markType)
     957             :         {
     958             :             case ROW_MARK_EXCLUSIVE:
     959             :             case ROW_MARK_NOKEYEXCLUSIVE:
     960             :             case ROW_MARK_SHARE:
     961             :             case ROW_MARK_KEYSHARE:
     962         377 :                 relation = heap_open(relid, RowShareLock);
     963         377 :                 break;
     964             :             case ROW_MARK_REFERENCE:
     965         157 :                 relation = heap_open(relid, AccessShareLock);
     966         157 :                 break;
     967             :             case ROW_MARK_COPY:
     968             :                 /* no physical table access is required */
     969          22 :                 relation = NULL;
     970          22 :                 break;
     971             :             default:
     972           0 :                 elog(ERROR, "unrecognized markType: %d", rc->markType);
     973             :                 relation = NULL;    /* keep compiler quiet */
     974             :                 break;
     975             :         }
     976             : 
     977             :         /* Check that relation is a legal target for marking */
     978         556 :         if (relation)
     979         534 :             CheckValidRowMarkRel(relation, rc->markType);
     980             : 
     981         555 :         erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
     982         555 :         erm->relation = relation;
     983         555 :         erm->relid = relid;
     984         555 :         erm->rti = rc->rti;
     985         555 :         erm->prti = rc->prti;
     986         555 :         erm->rowmarkId = rc->rowmarkId;
     987         555 :         erm->markType = rc->markType;
     988         555 :         erm->strength = rc->strength;
     989         555 :         erm->waitPolicy = rc->waitPolicy;
     990         555 :         erm->ermActive = false;
     991         555 :         ItemPointerSetInvalid(&(erm->curCtid));
     992         555 :         erm->ermExtra = NULL;
     993         555 :         estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
     994             :     }
     995             : 
     996             :     /*
     997             :      * Initialize the executor's tuple table to empty.
     998             :      */
     999       24592 :     estate->es_tupleTable = NIL;
    1000       24592 :     estate->es_trig_tuple_slot = NULL;
    1001       24592 :     estate->es_trig_oldtup_slot = NULL;
    1002       24592 :     estate->es_trig_newtup_slot = NULL;
    1003             : 
    1004             :     /* mark EvalPlanQual not active */
    1005       24592 :     estate->es_epqTuple = NULL;
    1006       24592 :     estate->es_epqTupleSet = NULL;
    1007       24592 :     estate->es_epqScanDone = NULL;
    1008             : 
    1009             :     /*
    1010             :      * Initialize private state information for each SubPlan.  We must do this
    1011             :      * before running ExecInitNode on the main query tree, since
    1012             :      * ExecInitSubPlan expects to be able to find these entries.
    1013             :      */
    1014       24592 :     Assert(estate->es_subplanstates == NIL);
    1015       24592 :     i = 1;                      /* subplan indices count from 1 */
    1016       27816 :     foreach(l, plannedstmt->subplans)
    1017             :     {
    1018        3224 :         Plan       *subplan = (Plan *) lfirst(l);
    1019             :         PlanState  *subplanstate;
    1020             :         int         sp_eflags;
    1021             : 
    1022             :         /*
    1023             :          * A subplan will never need to do BACKWARD scan nor MARK/RESTORE. If
    1024             :          * it is a parameterless subplan (not initplan), we suggest that it be
    1025             :          * prepared to handle REWIND efficiently; otherwise there is no need.
    1026             :          */
    1027        3224 :         sp_eflags = eflags
    1028             :             & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA);
    1029        3224 :         if (bms_is_member(i, plannedstmt->rewindPlanIDs))
    1030           2 :             sp_eflags |= EXEC_FLAG_REWIND;
    1031             : 
    1032        3224 :         subplanstate = ExecInitNode(subplan, estate, sp_eflags);
    1033             : 
    1034        3224 :         estate->es_subplanstates = lappend(estate->es_subplanstates,
    1035             :                                            subplanstate);
    1036             : 
    1037        3224 :         i++;
    1038             :     }
    1039             : 
    1040             :     /*
    1041             :      * Initialize the private state information for all the nodes in the query
    1042             :      * tree.  This opens files, allocates storage and leaves us ready to start
    1043             :      * processing tuples.
    1044             :      */
    1045       24592 :     planstate = ExecInitNode(plan, estate, eflags);
    1046             : 
    1047             :     /*
    1048             :      * Get the tuple descriptor describing the type of tuples to return.
    1049             :      */
    1050       24588 :     tupType = ExecGetResultType(planstate);
    1051             : 
    1052             :     /*
    1053             :      * Initialize the junk filter if needed.  SELECT queries need a filter if
    1054             :      * there are any junk attrs in the top-level tlist.
    1055             :      */
    1056       24588 :     if (operation == CMD_SELECT)
    1057             :     {
    1058       20136 :         bool        junk_filter_needed = false;
    1059             :         ListCell   *tlist;
    1060             : 
    1061       62250 :         foreach(tlist, plan->targetlist)
    1062             :         {
    1063       43105 :             TargetEntry *tle = (TargetEntry *) lfirst(tlist);
    1064             : 
    1065       43105 :             if (tle->resjunk)
    1066             :             {
    1067         991 :                 junk_filter_needed = true;
    1068         991 :                 break;
    1069             :             }
    1070             :         }
    1071             : 
    1072       20136 :         if (junk_filter_needed)
    1073             :         {
    1074             :             JunkFilter *j;
    1075             : 
    1076        1982 :             j = ExecInitJunkFilter(planstate->plan->targetlist,
    1077         991 :                                    tupType->tdhasoid,
    1078             :                                    ExecInitExtraTupleSlot(estate));
    1079         991 :             estate->es_junkFilter = j;
    1080             : 
    1081             :             /* Want to return the cleaned tuple type */
    1082         991 :             tupType = j->jf_cleanTupType;
    1083             :         }
    1084             :     }
    1085             : 
    1086       24588 :     queryDesc->tupDesc = tupType;
    1087       24588 :     queryDesc->planstate = planstate;
    1088       24588 : }
    1089             : 
    1090             : /*
    1091             :  * Check that a proposed result relation is a legal target for the operation
    1092             :  *
    1093             :  * Generally the parser and/or planner should have noticed any such mistake
    1094             :  * already, but let's make sure.
    1095             :  *
    1096             :  * Note: when changing this function, you probably also need to look at
    1097             :  * CheckValidRowMarkRel.
    1098             :  */
    1099             : void
    1100        4832 : CheckValidResultRel(Relation resultRel, CmdType operation)
    1101             : {
    1102        4832 :     TriggerDesc *trigDesc = resultRel->trigdesc;
    1103             :     FdwRoutine *fdwroutine;
    1104             : 
    1105        4832 :     switch (resultRel->rd_rel->relkind)
    1106             :     {
    1107             :         case RELKIND_RELATION:
    1108             :         case RELKIND_PARTITIONED_TABLE:
    1109        4778 :             CheckCmdReplicaIdentity(resultRel, operation);
    1110        4778 :             break;
    1111             :         case RELKIND_SEQUENCE:
    1112           0 :             ereport(ERROR,
    1113             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1114             :                      errmsg("cannot change sequence \"%s\"",
    1115             :                             RelationGetRelationName(resultRel))));
    1116             :             break;
    1117             :         case RELKIND_TOASTVALUE:
    1118           0 :             ereport(ERROR,
    1119             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1120             :                      errmsg("cannot change TOAST relation \"%s\"",
    1121             :                             RelationGetRelationName(resultRel))));
    1122             :             break;
    1123             :         case RELKIND_VIEW:
    1124             : 
    1125             :             /*
    1126             :              * Okay only if there's a suitable INSTEAD OF trigger.  Messages
    1127             :              * here should match rewriteHandler.c's rewriteTargetView, except
    1128             :              * that we omit errdetail because we haven't got the information
    1129             :              * handy (and given that we really shouldn't get here anyway, it's
    1130             :              * not worth great exertion to get).
    1131             :              */
    1132          44 :             switch (operation)
    1133             :             {
    1134             :                 case CMD_INSERT:
    1135          14 :                     if (!trigDesc || !trigDesc->trig_insert_instead_row)
    1136           0 :                         ereport(ERROR,
    1137             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1138             :                                  errmsg("cannot insert into view \"%s\"",
    1139             :                                         RelationGetRelationName(resultRel)),
    1140             :                                  errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
    1141          14 :                     break;
    1142             :                 case CMD_UPDATE:
    1143          22 :                     if (!trigDesc || !trigDesc->trig_update_instead_row)
    1144           0 :                         ereport(ERROR,
    1145             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1146             :                                  errmsg("cannot update view \"%s\"",
    1147             :                                         RelationGetRelationName(resultRel)),
    1148             :                                  errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
    1149          22 :                     break;
    1150             :                 case CMD_DELETE:
    1151           8 :                     if (!trigDesc || !trigDesc->trig_delete_instead_row)
    1152           0 :                         ereport(ERROR,
    1153             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1154             :                                  errmsg("cannot delete from view \"%s\"",
    1155             :                                         RelationGetRelationName(resultRel)),
    1156             :                                  errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
    1157           8 :                     break;
    1158             :                 default:
    1159           0 :                     elog(ERROR, "unrecognized CmdType: %d", (int) operation);
    1160             :                     break;
    1161             :             }
    1162          44 :             break;
    1163             :         case RELKIND_MATVIEW:
    1164          10 :             if (!MatViewIncrementalMaintenanceIsEnabled())
    1165           0 :                 ereport(ERROR,
    1166             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1167             :                          errmsg("cannot change materialized view \"%s\"",
    1168             :                                 RelationGetRelationName(resultRel))));
    1169          10 :             break;
    1170             :         case RELKIND_FOREIGN_TABLE:
    1171             :             /* Okay only if the FDW supports it */
    1172           0 :             fdwroutine = GetFdwRoutineForRelation(resultRel, false);
    1173           0 :             switch (operation)
    1174             :             {
    1175             :                 case CMD_INSERT:
    1176           0 :                     if (fdwroutine->ExecForeignInsert == NULL)
    1177           0 :                         ereport(ERROR,
    1178             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1179             :                                  errmsg("cannot insert into foreign table \"%s\"",
    1180             :                                         RelationGetRelationName(resultRel))));
    1181           0 :                     if (fdwroutine->IsForeignRelUpdatable != NULL &&
    1182           0 :                         (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
    1183           0 :                         ereport(ERROR,
    1184             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1185             :                                  errmsg("foreign table \"%s\" does not allow inserts",
    1186             :                                         RelationGetRelationName(resultRel))));
    1187           0 :                     break;
    1188             :                 case CMD_UPDATE:
    1189           0 :                     if (fdwroutine->ExecForeignUpdate == NULL)
    1190           0 :                         ereport(ERROR,
    1191             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1192             :                                  errmsg("cannot update foreign table \"%s\"",
    1193             :                                         RelationGetRelationName(resultRel))));
    1194           0 :                     if (fdwroutine->IsForeignRelUpdatable != NULL &&
    1195           0 :                         (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
    1196           0 :                         ereport(ERROR,
    1197             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1198             :                                  errmsg("foreign table \"%s\" does not allow updates",
    1199             :                                         RelationGetRelationName(resultRel))));
    1200           0 :                     break;
    1201             :                 case CMD_DELETE:
    1202           0 :                     if (fdwroutine->ExecForeignDelete == NULL)
    1203           0 :                         ereport(ERROR,
    1204             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1205             :                                  errmsg("cannot delete from foreign table \"%s\"",
    1206             :                                         RelationGetRelationName(resultRel))));
    1207           0 :                     if (fdwroutine->IsForeignRelUpdatable != NULL &&
    1208           0 :                         (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
    1209           0 :                         ereport(ERROR,
    1210             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1211             :                                  errmsg("foreign table \"%s\" does not allow deletes",
    1212             :                                         RelationGetRelationName(resultRel))));
    1213           0 :                     break;
    1214             :                 default:
    1215           0 :                     elog(ERROR, "unrecognized CmdType: %d", (int) operation);
    1216             :                     break;
    1217             :             }
    1218           0 :             break;
    1219             :         default:
    1220           0 :             ereport(ERROR,
    1221             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1222             :                      errmsg("cannot change relation \"%s\"",
    1223             :                             RelationGetRelationName(resultRel))));
    1224             :             break;
    1225             :     }
    1226        4832 : }
    1227             : 
    1228             : /*
    1229             :  * Check that a proposed rowmark target relation is a legal target
    1230             :  *
    1231             :  * In most cases parser and/or planner should have noticed this already, but
    1232             :  * they don't cover all cases.
    1233             :  */
    1234             : static void
    1235         534 : CheckValidRowMarkRel(Relation rel, RowMarkType markType)
    1236             : {
    1237             :     FdwRoutine *fdwroutine;
    1238             : 
    1239         534 :     switch (rel->rd_rel->relkind)
    1240             :     {
    1241             :         case RELKIND_RELATION:
    1242             :         case RELKIND_PARTITIONED_TABLE:
    1243             :             /* OK */
    1244         532 :             break;
    1245             :         case RELKIND_SEQUENCE:
    1246             :             /* Must disallow this because we don't vacuum sequences */
    1247           0 :             ereport(ERROR,
    1248             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1249             :                      errmsg("cannot lock rows in sequence \"%s\"",
    1250             :                             RelationGetRelationName(rel))));
    1251             :             break;
    1252             :         case RELKIND_TOASTVALUE:
    1253             :             /* We could allow this, but there seems no good reason to */
    1254           0 :             ereport(ERROR,
    1255             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1256             :                      errmsg("cannot lock rows in TOAST relation \"%s\"",
    1257             :                             RelationGetRelationName(rel))));
    1258             :             break;
    1259             :         case RELKIND_VIEW:
    1260             :             /* Should not get here; planner should have expanded the view */
    1261           0 :             ereport(ERROR,
    1262             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1263             :                      errmsg("cannot lock rows in view \"%s\"",
    1264             :                             RelationGetRelationName(rel))));
    1265             :             break;
    1266             :         case RELKIND_MATVIEW:
    1267             :             /* Allow referencing a matview, but not actual locking clauses */
    1268           2 :             if (markType != ROW_MARK_REFERENCE)
    1269           1 :                 ereport(ERROR,
    1270             :                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1271             :                          errmsg("cannot lock rows in materialized view \"%s\"",
    1272             :                                 RelationGetRelationName(rel))));
    1273           1 :             break;
    1274             :         case RELKIND_FOREIGN_TABLE:
    1275             :             /* Okay only if the FDW supports it */
    1276           0 :             fdwroutine = GetFdwRoutineForRelation(rel, false);
    1277           0 :             if (fdwroutine->RefetchForeignRow == NULL)
    1278           0 :                 ereport(ERROR,
    1279             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1280             :                          errmsg("cannot lock rows in foreign table \"%s\"",
    1281             :                                 RelationGetRelationName(rel))));
    1282           0 :             break;
    1283             :         default:
    1284           0 :             ereport(ERROR,
    1285             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1286             :                      errmsg("cannot lock rows in relation \"%s\"",
    1287             :                             RelationGetRelationName(rel))));
    1288             :             break;
    1289             :     }
    1290         533 : }
    1291             : 
    1292             : /*
    1293             :  * Initialize ResultRelInfo data for one result relation
    1294             :  *
    1295             :  * Caution: before Postgres 9.1, this function included the relkind checking
    1296             :  * that's now in CheckValidResultRel, and it also did ExecOpenIndices if
    1297             :  * appropriate.  Be sure callers cover those needs.
    1298             :  */
    1299             : void
    1300        5079 : InitResultRelInfo(ResultRelInfo *resultRelInfo,
    1301             :                   Relation resultRelationDesc,
    1302             :                   Index resultRelationIndex,
    1303             :                   Relation partition_root,
    1304             :                   int instrument_options)
    1305             : {
    1306        5079 :     List       *partition_check = NIL;
    1307             : 
    1308        5079 :     MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
    1309        5079 :     resultRelInfo->type = T_ResultRelInfo;
    1310        5079 :     resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
    1311        5079 :     resultRelInfo->ri_RelationDesc = resultRelationDesc;
    1312        5079 :     resultRelInfo->ri_NumIndices = 0;
    1313        5079 :     resultRelInfo->ri_IndexRelationDescs = NULL;
    1314        5079 :     resultRelInfo->ri_IndexRelationInfo = NULL;
    1315             :     /* make a copy so as not to depend on relcache info not changing... */
    1316        5079 :     resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
    1317        5079 :     if (resultRelInfo->ri_TrigDesc)
    1318             :     {
    1319        1119 :         int         n = resultRelInfo->ri_TrigDesc->numtriggers;
    1320             : 
    1321        1119 :         resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
    1322        1119 :             palloc0(n * sizeof(FmgrInfo));
    1323        1119 :         resultRelInfo->ri_TrigWhenExprs = (ExprState **)
    1324        1119 :             palloc0(n * sizeof(ExprState *));
    1325        1119 :         if (instrument_options)
    1326           0 :             resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options);
    1327             :     }
    1328             :     else
    1329             :     {
    1330        3960 :         resultRelInfo->ri_TrigFunctions = NULL;
    1331        3960 :         resultRelInfo->ri_TrigWhenExprs = NULL;
    1332        3960 :         resultRelInfo->ri_TrigInstrument = NULL;
    1333             :     }
    1334        5079 :     if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
    1335           0 :         resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
    1336             :     else
    1337        5079 :         resultRelInfo->ri_FdwRoutine = NULL;
    1338        5079 :     resultRelInfo->ri_FdwState = NULL;
    1339        5079 :     resultRelInfo->ri_usesFdwDirectModify = false;
    1340        5079 :     resultRelInfo->ri_ConstraintExprs = NULL;
    1341        5079 :     resultRelInfo->ri_junkFilter = NULL;
    1342        5079 :     resultRelInfo->ri_projectReturning = NULL;
    1343             : 
    1344             :     /*
    1345             :      * Partition constraint, which also includes the partition constraint of
    1346             :      * all the ancestors that are partitions.  Note that it will be checked
    1347             :      * even in the case of tuple-routing where this table is the target leaf
    1348             :      * partition, if there any BR triggers defined on the table.  Although
    1349             :      * tuple-routing implicitly preserves the partition constraint of the
    1350             :      * target partition for a given row, the BR triggers may change the row
    1351             :      * such that the constraint is no longer satisfied, which we must fail for
    1352             :      * by checking it explicitly.
    1353             :      *
    1354             :      * If this is a partitioned table, the partition constraint (if any) of a
    1355             :      * given row will be checked just before performing tuple-routing.
    1356             :      */
    1357        5079 :     partition_check = RelationGetPartitionQual(resultRelationDesc);
    1358             : 
    1359        5079 :     resultRelInfo->ri_PartitionCheck = partition_check;
    1360        5079 :     resultRelInfo->ri_PartitionRoot = partition_root;
    1361        5079 : }
    1362             : 
    1363             : /*
    1364             :  *      ExecGetTriggerResultRel
    1365             :  *
    1366             :  * Get a ResultRelInfo for a trigger target relation.  Most of the time,
    1367             :  * triggers are fired on one of the result relations of the query, and so
    1368             :  * we can just return a member of the es_result_relations array, the
    1369             :  * es_root_result_relations array (if any), or the es_leaf_result_relations
    1370             :  * list (if any).  (Note: in self-join situations there might be multiple
    1371             :  * members with the same OID; if so it doesn't matter which one we pick.)
    1372             :  * However, it is sometimes necessary to fire triggers on other relations;
    1373             :  * this happens mainly when an RI update trigger queues additional triggers
    1374             :  * on other relations, which will be processed in the context of the outer
    1375             :  * query.  For efficiency's sake, we want to have a ResultRelInfo for those
    1376             :  * triggers too; that can avoid repeated re-opening of the relation.  (It
    1377             :  * also provides a way for EXPLAIN ANALYZE to report the runtimes of such
    1378             :  * triggers.)  So we make additional ResultRelInfo's as needed, and save them
    1379             :  * in es_trig_target_relations.
    1380             :  */
    1381             : ResultRelInfo *
    1382         663 : ExecGetTriggerResultRel(EState *estate, Oid relid)
    1383             : {
    1384             :     ResultRelInfo *rInfo;
    1385             :     int         nr;
    1386             :     ListCell   *l;
    1387             :     Relation    rel;
    1388             :     MemoryContext oldcontext;
    1389             : 
    1390             :     /* First, search through the query result relations */
    1391         663 :     rInfo = estate->es_result_relations;
    1392         663 :     nr = estate->es_num_result_relations;
    1393        1363 :     while (nr > 0)
    1394             :     {
    1395         655 :         if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
    1396         618 :             return rInfo;
    1397          37 :         rInfo++;
    1398          37 :         nr--;
    1399             :     }
    1400             :     /* Second, search through the root result relations, if any */
    1401          45 :     rInfo = estate->es_root_result_relations;
    1402          45 :     nr = estate->es_num_root_result_relations;
    1403          91 :     while (nr > 0)
    1404             :     {
    1405           7 :         if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
    1406           6 :             return rInfo;
    1407           1 :         rInfo++;
    1408           1 :         nr--;
    1409             :     }
    1410             :     /* Third, search through the leaf result relations, if any */
    1411          41 :     foreach(l, estate->es_leaf_result_relations)
    1412             :     {
    1413           4 :         rInfo = (ResultRelInfo *) lfirst(l);
    1414           4 :         if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
    1415           2 :             return rInfo;
    1416             :     }
    1417             :     /* Nope, but maybe we already made an extra ResultRelInfo for it */
    1418          37 :     foreach(l, estate->es_trig_target_relations)
    1419             :     {
    1420           0 :         rInfo = (ResultRelInfo *) lfirst(l);
    1421           0 :         if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
    1422           0 :             return rInfo;
    1423             :     }
    1424             :     /* Nope, so we need a new one */
    1425             : 
    1426             :     /*
    1427             :      * Open the target relation's relcache entry.  We assume that an
    1428             :      * appropriate lock is still held by the backend from whenever the trigger
    1429             :      * event got queued, so we need take no new lock here.  Also, we need not
    1430             :      * recheck the relkind, so no need for CheckValidResultRel.
    1431             :      */
    1432          37 :     rel = heap_open(relid, NoLock);
    1433             : 
    1434             :     /*
    1435             :      * Make the new entry in the right context.
    1436             :      */
    1437          37 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    1438          37 :     rInfo = makeNode(ResultRelInfo);
    1439          37 :     InitResultRelInfo(rInfo,
    1440             :                       rel,
    1441             :                       0,        /* dummy rangetable index */
    1442             :                       NULL,
    1443             :                       estate->es_instrument);
    1444          37 :     estate->es_trig_target_relations =
    1445          37 :         lappend(estate->es_trig_target_relations, rInfo);
    1446          37 :     MemoryContextSwitchTo(oldcontext);
    1447             : 
    1448             :     /*
    1449             :      * Currently, we don't need any index information in ResultRelInfos used
    1450             :      * only for triggers, so no need to call ExecOpenIndices.
    1451             :      */
    1452             : 
    1453          37 :     return rInfo;
    1454             : }
    1455             : 
    1456             : /*
    1457             :  * Close any relations that have been opened by ExecGetTriggerResultRel().
    1458             :  */
    1459             : void
    1460       21422 : ExecCleanUpTriggerState(EState *estate)
    1461             : {
    1462             :     ListCell   *l;
    1463             : 
    1464       21442 :     foreach(l, estate->es_trig_target_relations)
    1465             :     {
    1466          20 :         ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
    1467             : 
    1468             :         /* Close indices and then the relation itself */
    1469          20 :         ExecCloseIndices(resultRelInfo);
    1470          20 :         heap_close(resultRelInfo->ri_RelationDesc, NoLock);
    1471             :     }
    1472       21422 : }
    1473             : 
    1474             : /*
    1475             :  *      ExecContextForcesOids
    1476             :  *
    1477             :  * This is pretty grotty: when doing INSERT, UPDATE, or CREATE TABLE AS,
    1478             :  * we need to ensure that result tuples have space for an OID iff they are
    1479             :  * going to be stored into a relation that has OIDs.  In other contexts
    1480             :  * we are free to choose whether to leave space for OIDs in result tuples
    1481             :  * (we generally don't want to, but we do if a physical-tlist optimization
    1482             :  * is possible).  This routine checks the plan context and returns TRUE if the
    1483             :  * choice is forced, FALSE if the choice is not forced.  In the TRUE case,
    1484             :  * *hasoids is set to the required value.
    1485             :  *
    1486             :  * One reason this is ugly is that all plan nodes in the plan tree will emit
    1487             :  * tuples with space for an OID, though we really only need the topmost node
    1488             :  * to do so.  However, node types like Sort don't project new tuples but just
    1489             :  * return their inputs, and in those cases the requirement propagates down
    1490             :  * to the input node.  Eventually we might make this code smart enough to
    1491             :  * recognize how far down the requirement really goes, but for now we just
    1492             :  * make all plan nodes do the same thing if the top level forces the choice.
    1493             :  *
    1494             :  * We assume that if we are generating tuples for INSERT or UPDATE,
    1495             :  * estate->es_result_relation_info is already set up to describe the target
    1496             :  * relation.  Note that in an UPDATE that spans an inheritance tree, some of
    1497             :  * the target relations may have OIDs and some not.  We have to make the
    1498             :  * decisions on a per-relation basis as we initialize each of the subplans of
    1499             :  * the ModifyTable node, so ModifyTable has to set es_result_relation_info
    1500             :  * while initializing each subplan.
    1501             :  *
    1502             :  * CREATE TABLE AS is even uglier, because we don't have the target relation's
    1503             :  * descriptor available when this code runs; we have to look aside at the
    1504             :  * flags passed to ExecutorStart().
    1505             :  */
    1506             : bool
    1507       54647 : ExecContextForcesOids(PlanState *planstate, bool *hasoids)
    1508             : {
    1509       54647 :     ResultRelInfo *ri = planstate->state->es_result_relation_info;
    1510             : 
    1511       54647 :     if (ri != NULL)
    1512             :     {
    1513        5670 :         Relation    rel = ri->ri_RelationDesc;
    1514             : 
    1515        5670 :         if (rel != NULL)
    1516             :         {
    1517        5670 :             *hasoids = rel->rd_rel->relhasoids;
    1518        5670 :             return true;
    1519             :         }
    1520             :     }
    1521             : 
    1522       48977 :     if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS)
    1523             :     {
    1524           2 :         *hasoids = true;
    1525           2 :         return true;
    1526             :     }
    1527       48975 :     if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS)
    1528             :     {
    1529         294 :         *hasoids = false;
    1530         294 :         return true;
    1531             :     }
    1532             : 
    1533       48681 :     return false;
    1534             : }
    1535             : 
    1536             : /* ----------------------------------------------------------------
    1537             :  *      ExecPostprocessPlan
    1538             :  *
    1539             :  *      Give plan nodes a final chance to execute before shutdown
    1540             :  * ----------------------------------------------------------------
    1541             :  */
    1542             : static void
    1543       20277 : ExecPostprocessPlan(EState *estate)
    1544             : {
    1545             :     ListCell   *lc;
    1546             : 
    1547             :     /*
    1548             :      * Make sure nodes run forward.
    1549             :      */
    1550       20277 :     estate->es_direction = ForwardScanDirection;
    1551             : 
    1552             :     /*
    1553             :      * Run any secondary ModifyTable nodes to completion, in case the main
    1554             :      * query did not fetch all rows from them.  (We do this to ensure that
    1555             :      * such nodes have predictable results.)
    1556             :      */
    1557       20394 :     foreach(lc, estate->es_auxmodifytables)
    1558             :     {
    1559         117 :         PlanState  *ps = (PlanState *) lfirst(lc);
    1560             : 
    1561             :         for (;;)
    1562             :         {
    1563             :             TupleTableSlot *slot;
    1564             : 
    1565             :             /* Reset the per-output-tuple exprcontext each time */
    1566         140 :             ResetPerTupleExprContext(estate);
    1567             : 
    1568         140 :             slot = ExecProcNode(ps);
    1569             : 
    1570         140 :             if (TupIsNull(slot))
    1571             :                 break;
    1572          23 :         }
    1573             :     }
    1574       20277 : }
    1575             : 
    1576             : /* ----------------------------------------------------------------
    1577             :  *      ExecEndPlan
    1578             :  *
    1579             :  *      Cleans up the query plan -- closes files and frees up storage
    1580             :  *
    1581             :  * NOTE: we are no longer very worried about freeing storage per se
    1582             :  * in this code; FreeExecutorState should be guaranteed to release all
    1583             :  * memory that needs to be released.  What we are worried about doing
    1584             :  * is closing relations and dropping buffer pins.  Thus, for example,
    1585             :  * tuple tables must be cleared or dropped to ensure pins are released.
    1586             :  * ----------------------------------------------------------------
    1587             :  */
    1588             : static void
    1589       21321 : ExecEndPlan(PlanState *planstate, EState *estate)
    1590             : {
    1591             :     ResultRelInfo *resultRelInfo;
    1592             :     int         i;
    1593             :     ListCell   *l;
    1594             : 
    1595             :     /*
    1596             :      * shut down the node-type-specific query processing
    1597             :      */
    1598       21321 :     ExecEndNode(planstate);
    1599             : 
    1600             :     /*
    1601             :      * for subplans too
    1602             :      */
    1603       24490 :     foreach(l, estate->es_subplanstates)
    1604             :     {
    1605        3169 :         PlanState  *subplanstate = (PlanState *) lfirst(l);
    1606             : 
    1607        3169 :         ExecEndNode(subplanstate);
    1608             :     }
    1609             : 
    1610             :     /*
    1611             :      * destroy the executor's tuple table.  Actually we only care about
    1612             :      * releasing buffer pins and tupdesc refcounts; there's no need to pfree
    1613             :      * the TupleTableSlots, since the containing memory context is about to go
    1614             :      * away anyway.
    1615             :      */
    1616       21321 :     ExecResetTupleTable(estate->es_tupleTable, false);
    1617             : 
    1618             :     /*
    1619             :      * close the result relation(s) if any, but hold locks until xact commit.
    1620             :      */
    1621       21321 :     resultRelInfo = estate->es_result_relations;
    1622       25589 :     for (i = estate->es_num_result_relations; i > 0; i--)
    1623             :     {
    1624             :         /* Close indices and then the relation itself */
    1625        4268 :         ExecCloseIndices(resultRelInfo);
    1626        4268 :         heap_close(resultRelInfo->ri_RelationDesc, NoLock);
    1627        4268 :         resultRelInfo++;
    1628             :     }
    1629             : 
    1630             :     /* Close the root target relation(s). */
    1631       21321 :     resultRelInfo = estate->es_root_result_relations;
    1632       21331 :     for (i = estate->es_num_root_result_relations; i > 0; i--)
    1633             :     {
    1634          10 :         heap_close(resultRelInfo->ri_RelationDesc, NoLock);
    1635          10 :         resultRelInfo++;
    1636             :     }
    1637             : 
    1638             :     /* likewise close any trigger target relations */
    1639       21321 :     ExecCleanUpTriggerState(estate);
    1640             : 
    1641             :     /*
    1642             :      * close any relations selected FOR [KEY] UPDATE/SHARE, again keeping
    1643             :      * locks
    1644             :      */
    1645       21862 :     foreach(l, estate->es_rowMarks)
    1646             :     {
    1647         541 :         ExecRowMark *erm = (ExecRowMark *) lfirst(l);
    1648             : 
    1649         541 :         if (erm->relation)
    1650         519 :             heap_close(erm->relation, NoLock);
    1651             :     }
    1652       21321 : }
    1653             : 
    1654             : /* ----------------------------------------------------------------
    1655             :  *      ExecutePlan
    1656             :  *
    1657             :  *      Processes the query plan until we have retrieved 'numberTuples' tuples,
    1658             :  *      moving in the specified direction.
    1659             :  *
    1660             :  *      Runs to completion if numberTuples is 0
    1661             :  *
    1662             :  * Note: the ctid attribute is a 'junk' attribute that is removed before the
    1663             :  * user can see it
    1664             :  * ----------------------------------------------------------------
    1665             :  */
    1666             : static void
    1667       23779 : ExecutePlan(EState *estate,
    1668             :             PlanState *planstate,
    1669             :             bool use_parallel_mode,
    1670             :             CmdType operation,
    1671             :             bool sendTuples,
    1672             :             uint64 numberTuples,
    1673             :             ScanDirection direction,
    1674             :             DestReceiver *dest,
    1675             :             bool execute_once)
    1676             : {
    1677             :     TupleTableSlot *slot;
    1678             :     uint64      current_tuple_count;
    1679             : 
    1680             :     /*
    1681             :      * initialize local variables
    1682             :      */
    1683       23779 :     current_tuple_count = 0;
    1684             : 
    1685             :     /*
    1686             :      * Set the direction.
    1687             :      */
    1688       23779 :     estate->es_direction = direction;
    1689             : 
    1690             :     /*
    1691             :      * If the plan might potentially be executed multiple times, we must force
    1692             :      * it to run without parallelism, because we might exit early.  Also
    1693             :      * disable parallelism when writing into a relation, because no database
    1694             :      * changes are allowed in parallel mode.
    1695             :      */
    1696       23779 :     if (!execute_once || dest->mydest == DestIntoRel)
    1697        1262 :         use_parallel_mode = false;
    1698             : 
    1699       23779 :     if (use_parallel_mode)
    1700          17 :         EnterParallelMode();
    1701             : 
    1702             :     /*
    1703             :      * Loop until we've processed the proper number of tuples from the plan.
    1704             :      */
    1705             :     for (;;)
    1706             :     {
    1707             :         /* Reset the per-output-tuple exprcontext */
    1708      186065 :         ResetPerTupleExprContext(estate);
    1709             : 
    1710             :         /*
    1711             :          * Execute the plan and obtain a tuple
    1712             :          */
    1713      186065 :         slot = ExecProcNode(planstate);
    1714             : 
    1715             :         /*
    1716             :          * if the tuple is null, then we assume there is nothing more to
    1717             :          * process so we just end the loop...
    1718             :          */
    1719      182911 :         if (TupIsNull(slot))
    1720             :         {
    1721             :             /* Allow nodes to release or shut down resources. */
    1722       17704 :             (void) ExecShutdownNode(planstate);
    1723       17704 :             break;
    1724             :         }
    1725             : 
    1726             :         /*
    1727             :          * If we have a junk filter, then project a new tuple with the junk
    1728             :          * removed.
    1729             :          *
    1730             :          * Store this new "clean" tuple in the junkfilter's resultSlot.
    1731             :          * (Formerly, we stored it back over the "dirty" tuple, which is WRONG
    1732             :          * because that tuple slot has the wrong descriptor.)
    1733             :          */
    1734      165207 :         if (estate->es_junkFilter != NULL)
    1735        2786 :             slot = ExecFilterJunk(estate->es_junkFilter, slot);
    1736             : 
    1737             :         /*
    1738             :          * If we are supposed to send the tuple somewhere, do so. (In
    1739             :          * practice, this is probably always the case at this point.)
    1740             :          */
    1741      165207 :         if (sendTuples)
    1742             :         {
    1743             :             /*
    1744             :              * If we are not able to send the tuple, we assume the destination
    1745             :              * has closed and no more tuples can be sent. If that's the case,
    1746             :              * end the loop.
    1747             :              */
    1748      165207 :             if (!((*dest->receiveSlot) (slot, dest)))
    1749           0 :                 break;
    1750             :         }
    1751             : 
    1752             :         /*
    1753             :          * Count tuples processed, if this is a SELECT.  (For other operation
    1754             :          * types, the ModifyTable plan node must count the appropriate
    1755             :          * events.)
    1756             :          */
    1757      165207 :         if (operation == CMD_SELECT)
    1758      164885 :             (estate->es_processed)++;
    1759             : 
    1760             :         /*
    1761             :          * check our tuple count.. if we've processed the proper number then
    1762             :          * quit, else loop again and process more tuples.  Zero numberTuples
    1763             :          * means no limit.
    1764             :          */
    1765      165207 :         current_tuple_count++;
    1766      165207 :         if (numberTuples && numberTuples == current_tuple_count)
    1767             :         {
    1768             :             /* Allow nodes to release or shut down resources. */
    1769        2921 :             (void) ExecShutdownNode(planstate);
    1770        2921 :             break;
    1771             :         }
    1772      162286 :     }
    1773             : 
    1774       20625 :     if (use_parallel_mode)
    1775          16 :         ExitParallelMode();
    1776       20625 : }
    1777             : 
    1778             : 
    1779             : /*
    1780             :  * ExecRelCheck --- check that tuple meets constraints for result relation
    1781             :  *
    1782             :  * Returns NULL if OK, else name of failed check constraint
    1783             :  */
    1784             : static const char *
    1785         191 : ExecRelCheck(ResultRelInfo *resultRelInfo,
    1786             :              TupleTableSlot *slot, EState *estate)
    1787             : {
    1788         191 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    1789         191 :     int         ncheck = rel->rd_att->constr->num_check;
    1790         191 :     ConstrCheck *check = rel->rd_att->constr->check;
    1791             :     ExprContext *econtext;
    1792             :     MemoryContext oldContext;
    1793             :     int         i;
    1794             : 
    1795             :     /*
    1796             :      * If first time through for this result relation, build expression
    1797             :      * nodetrees for rel's constraint expressions.  Keep them in the per-query
    1798             :      * memory context so they'll survive throughout the query.
    1799             :      */
    1800         191 :     if (resultRelInfo->ri_ConstraintExprs == NULL)
    1801             :     {
    1802         112 :         oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
    1803         112 :         resultRelInfo->ri_ConstraintExprs =
    1804         112 :             (ExprState **) palloc(ncheck * sizeof(ExprState *));
    1805         260 :         for (i = 0; i < ncheck; i++)
    1806             :         {
    1807             :             Expr       *checkconstr;
    1808             : 
    1809         148 :             checkconstr = stringToNode(check[i].ccbin);
    1810         296 :             resultRelInfo->ri_ConstraintExprs[i] =
    1811         148 :                 ExecPrepareExpr(checkconstr, estate);
    1812             :         }
    1813         112 :         MemoryContextSwitchTo(oldContext);
    1814             :     }
    1815             : 
    1816             :     /*
    1817             :      * We will use the EState's per-tuple context for evaluating constraint
    1818             :      * expressions (creating it if it's not already there).
    1819             :      */
    1820         191 :     econtext = GetPerTupleExprContext(estate);
    1821             : 
    1822             :     /* Arrange for econtext's scan tuple to be the tuple under test */
    1823         191 :     econtext->ecxt_scantuple = slot;
    1824             : 
    1825             :     /* And evaluate the constraints */
    1826         412 :     for (i = 0; i < ncheck; i++)
    1827             :     {
    1828         271 :         ExprState  *checkconstr = resultRelInfo->ri_ConstraintExprs[i];
    1829             : 
    1830             :         /*
    1831             :          * NOTE: SQL specifies that a NULL result from a constraint expression
    1832             :          * is not to be treated as a failure.  Therefore, use ExecCheck not
    1833             :          * ExecQual.
    1834             :          */
    1835         271 :         if (!ExecCheck(checkconstr, econtext))
    1836          50 :             return check[i].ccname;
    1837             :     }
    1838             : 
    1839             :     /* NULL result means no error */
    1840         141 :     return NULL;
    1841             : }
    1842             : 
    1843             : /*
    1844             :  * ExecPartitionCheck --- check that tuple meets the partition constraint.
    1845             :  */
    1846             : static void
    1847         107 : ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
    1848             :                    EState *estate)
    1849             : {
    1850         107 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    1851         107 :     TupleDesc   tupdesc = RelationGetDescr(rel);
    1852             :     Bitmapset  *modifiedCols;
    1853             :     Bitmapset  *insertedCols;
    1854             :     Bitmapset  *updatedCols;
    1855             :     ExprContext *econtext;
    1856             : 
    1857             :     /*
    1858             :      * If first time through, build expression state tree for the partition
    1859             :      * check expression.  Keep it in the per-query memory context so they'll
    1860             :      * survive throughout the query.
    1861             :      */
    1862         107 :     if (resultRelInfo->ri_PartitionCheckExpr == NULL)
    1863             :     {
    1864          72 :         List       *qual = resultRelInfo->ri_PartitionCheck;
    1865             : 
    1866          72 :         resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
    1867             :     }
    1868             : 
    1869             :     /*
    1870             :      * We will use the EState's per-tuple context for evaluating constraint
    1871             :      * expressions (creating it if it's not already there).
    1872             :      */
    1873         107 :     econtext = GetPerTupleExprContext(estate);
    1874             : 
    1875             :     /* Arrange for econtext's scan tuple to be the tuple under test */
    1876         107 :     econtext->ecxt_scantuple = slot;
    1877             : 
    1878             :     /*
    1879             :      * As in case of the catalogued constraints, we treat a NULL result as
    1880             :      * success here, not a failure.
    1881             :      */
    1882         107 :     if (!ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext))
    1883             :     {
    1884             :         char       *val_desc;
    1885          20 :         Relation    orig_rel = rel;
    1886             : 
    1887             :         /* See the comment above. */
    1888          20 :         if (resultRelInfo->ri_PartitionRoot)
    1889             :         {
    1890           3 :             HeapTuple   tuple = ExecFetchSlotTuple(slot);
    1891           3 :             TupleDesc   old_tupdesc = RelationGetDescr(rel);
    1892             :             TupleConversionMap *map;
    1893             : 
    1894           3 :             rel = resultRelInfo->ri_PartitionRoot;
    1895           3 :             tupdesc = RelationGetDescr(rel);
    1896             :             /* a reverse map */
    1897           3 :             map = convert_tuples_by_name(old_tupdesc, tupdesc,
    1898             :                                          gettext_noop("could not convert row type"));
    1899           3 :             if (map != NULL)
    1900             :             {
    1901           1 :                 tuple = do_convert_tuple(tuple, map);
    1902           1 :                 ExecSetSlotDescriptor(slot, tupdesc);
    1903           1 :                 ExecStoreTuple(tuple, slot, InvalidBuffer, false);
    1904             :             }
    1905             :         }
    1906             : 
    1907          20 :         insertedCols = GetInsertedColumns(resultRelInfo, estate);
    1908          20 :         updatedCols = GetUpdatedColumns(resultRelInfo, estate);
    1909          20 :         modifiedCols = bms_union(insertedCols, updatedCols);
    1910          20 :         val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
    1911             :                                                  slot,
    1912             :                                                  tupdesc,
    1913             :                                                  modifiedCols,
    1914             :                                                  64);
    1915          20 :         ereport(ERROR,
    1916             :                 (errcode(ERRCODE_CHECK_VIOLATION),
    1917             :                  errmsg("new row for relation \"%s\" violates partition constraint",
    1918             :                         RelationGetRelationName(orig_rel)),
    1919             :                  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
    1920             :     }
    1921          87 : }
    1922             : 
    1923             : /*
    1924             :  * ExecConstraints - check constraints of the tuple in 'slot'
    1925             :  *
    1926             :  * This checks the traditional NOT NULL and check constraints, as well as
    1927             :  * the partition constraint, if any.
    1928             :  *
    1929             :  * Note: 'slot' contains the tuple to check the constraints of, which may
    1930             :  * have been converted from the original input tuple after tuple routing.
    1931             :  * 'resultRelInfo' is the original result relation, before tuple routing.
    1932             :  */
    1933             : void
    1934       35641 : ExecConstraints(ResultRelInfo *resultRelInfo,
    1935             :                 TupleTableSlot *slot, EState *estate)
    1936             : {
    1937       35641 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    1938       35641 :     TupleDesc   tupdesc = RelationGetDescr(rel);
    1939       35641 :     TupleConstr *constr = tupdesc->constr;
    1940             :     Bitmapset  *modifiedCols;
    1941             :     Bitmapset  *insertedCols;
    1942             :     Bitmapset  *updatedCols;
    1943             : 
    1944       35641 :     Assert(constr || resultRelInfo->ri_PartitionCheck);
    1945             : 
    1946       35641 :     if (constr && constr->has_not_null)
    1947             :     {
    1948       35294 :         int         natts = tupdesc->natts;
    1949             :         int         attrChk;
    1950             : 
    1951      167528 :         for (attrChk = 1; attrChk <= natts; attrChk++)
    1952             :         {
    1953      132260 :             Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
    1954             : 
    1955      132260 :             if (att->attnotnull && slot_attisnull(slot, attrChk))
    1956             :             {
    1957             :                 char       *val_desc;
    1958          26 :                 Relation    orig_rel = rel;
    1959          26 :                 TupleDesc   orig_tupdesc = RelationGetDescr(rel);
    1960             : 
    1961             :                 /*
    1962             :                  * If the tuple has been routed, it's been converted to the
    1963             :                  * partition's rowtype, which might differ from the root
    1964             :                  * table's.  We must convert it back to the root table's
    1965             :                  * rowtype so that val_desc shown error message matches the
    1966             :                  * input tuple.
    1967             :                  */
    1968          26 :                 if (resultRelInfo->ri_PartitionRoot)
    1969             :                 {
    1970           0 :                     HeapTuple   tuple = ExecFetchSlotTuple(slot);
    1971             :                     TupleConversionMap *map;
    1972             : 
    1973           0 :                     rel = resultRelInfo->ri_PartitionRoot;
    1974           0 :                     tupdesc = RelationGetDescr(rel);
    1975             :                     /* a reverse map */
    1976           0 :                     map = convert_tuples_by_name(orig_tupdesc, tupdesc,
    1977             :                                                  gettext_noop("could not convert row type"));
    1978           0 :                     if (map != NULL)
    1979             :                     {
    1980           0 :                         tuple = do_convert_tuple(tuple, map);
    1981           0 :                         ExecSetSlotDescriptor(slot, tupdesc);
    1982           0 :                         ExecStoreTuple(tuple, slot, InvalidBuffer, false);
    1983             :                     }
    1984             :                 }
    1985             : 
    1986          26 :                 insertedCols = GetInsertedColumns(resultRelInfo, estate);
    1987          26 :                 updatedCols = GetUpdatedColumns(resultRelInfo, estate);
    1988          26 :                 modifiedCols = bms_union(insertedCols, updatedCols);
    1989          26 :                 val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
    1990             :                                                          slot,
    1991             :                                                          tupdesc,
    1992             :                                                          modifiedCols,
    1993             :                                                          64);
    1994             : 
    1995          26 :                 ereport(ERROR,
    1996             :                         (errcode(ERRCODE_NOT_NULL_VIOLATION),
    1997             :                          errmsg("null value in column \"%s\" violates not-null constraint",
    1998             :                                 NameStr(att->attname)),
    1999             :                          val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
    2000             :                          errtablecol(orig_rel, attrChk)));
    2001             :             }
    2002             :         }
    2003             :     }
    2004             : 
    2005       35615 :     if (constr && constr->num_check > 0)
    2006             :     {
    2007             :         const char *failed;
    2008             : 
    2009         191 :         if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
    2010             :         {
    2011             :             char       *val_desc;
    2012          50 :             Relation    orig_rel = rel;
    2013             : 
    2014             :             /* See the comment above. */
    2015          50 :             if (resultRelInfo->ri_PartitionRoot)
    2016             :             {
    2017           2 :                 HeapTuple   tuple = ExecFetchSlotTuple(slot);
    2018           2 :                 TupleDesc   old_tupdesc = RelationGetDescr(rel);
    2019             :                 TupleConversionMap *map;
    2020             : 
    2021           2 :                 rel = resultRelInfo->ri_PartitionRoot;
    2022           2 :                 tupdesc = RelationGetDescr(rel);
    2023             :                 /* a reverse map */
    2024           2 :                 map = convert_tuples_by_name(old_tupdesc, tupdesc,
    2025             :                                              gettext_noop("could not convert row type"));
    2026           2 :                 if (map != NULL)
    2027             :                 {
    2028           2 :                     tuple = do_convert_tuple(tuple, map);
    2029           2 :                     ExecSetSlotDescriptor(slot, tupdesc);
    2030           2 :                     ExecStoreTuple(tuple, slot, InvalidBuffer, false);
    2031             :                 }
    2032             :             }
    2033             : 
    2034          50 :             insertedCols = GetInsertedColumns(resultRelInfo, estate);
    2035          50 :             updatedCols = GetUpdatedColumns(resultRelInfo, estate);
    2036          50 :             modifiedCols = bms_union(insertedCols, updatedCols);
    2037          50 :             val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
    2038             :                                                      slot,
    2039             :                                                      tupdesc,
    2040             :                                                      modifiedCols,
    2041             :                                                      64);
    2042          50 :             ereport(ERROR,
    2043             :                     (errcode(ERRCODE_CHECK_VIOLATION),
    2044             :                      errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
    2045             :                             RelationGetRelationName(orig_rel), failed),
    2046             :                      val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
    2047             :                      errtableconstraint(orig_rel, failed)));
    2048             :         }
    2049             :     }
    2050             : 
    2051       35565 :     if (resultRelInfo->ri_PartitionCheck)
    2052         103 :         ExecPartitionCheck(resultRelInfo, slot, estate);
    2053       35546 : }
    2054             : 
    2055             : 
    2056             : /*
    2057             :  * ExecWithCheckOptions -- check that tuple satisfies any WITH CHECK OPTIONs
    2058             :  * of the specified kind.
    2059             :  *
    2060             :  * Note that this needs to be called multiple times to ensure that all kinds of
    2061             :  * WITH CHECK OPTIONs are handled (both those from views which have the WITH
    2062             :  * CHECK OPTION set and from row level security policies).  See ExecInsert()
    2063             :  * and ExecUpdate().
    2064             :  */
    2065             : void
    2066         241 : ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
    2067             :                      TupleTableSlot *slot, EState *estate)
    2068             : {
    2069         241 :     Relation    rel = resultRelInfo->ri_RelationDesc;
    2070         241 :     TupleDesc   tupdesc = RelationGetDescr(rel);
    2071             :     ExprContext *econtext;
    2072             :     ListCell   *l1,
    2073             :                *l2;
    2074             : 
    2075             :     /*
    2076             :      * We will use the EState's per-tuple context for evaluating constraint
    2077             :      * expressions (creating it if it's not already there).
    2078             :      */
    2079         241 :     econtext = GetPerTupleExprContext(estate);
    2080             : 
    2081             :     /* Arrange for econtext's scan tuple to be the tuple under test */
    2082         241 :     econtext->ecxt_scantuple = slot;
    2083             : 
    2084             :     /* Check each of the constraints */
    2085         507 :     forboth(l1, resultRelInfo->ri_WithCheckOptions,
    2086             :             l2, resultRelInfo->ri_WithCheckOptionExprs)
    2087             :     {
    2088         321 :         WithCheckOption *wco = (WithCheckOption *) lfirst(l1);
    2089         321 :         ExprState  *wcoExpr = (ExprState *) lfirst(l2);
    2090             : 
    2091             :         /*
    2092             :          * Skip any WCOs which are not the kind we are looking for at this
    2093             :          * time.
    2094             :          */
    2095         321 :         if (wco->kind != kind)
    2096         160 :             continue;
    2097             : 
    2098             :         /*
    2099             :          * WITH CHECK OPTION checks are intended to ensure that the new tuple
    2100             :          * is visible (in the case of a view) or that it passes the
    2101             :          * 'with-check' policy (in the case of row security). If the qual
    2102             :          * evaluates to NULL or FALSE, then the new tuple won't be included in
    2103             :          * the view or doesn't pass the 'with-check' policy for the table.
    2104             :          */
    2105         161 :         if (!ExecQual(wcoExpr, econtext))
    2106             :         {
    2107             :             char       *val_desc;
    2108             :             Bitmapset  *modifiedCols;
    2109             :             Bitmapset  *insertedCols;
    2110             :             Bitmapset  *updatedCols;
    2111             : 
    2112          55 :             switch (wco->kind)
    2113             :             {
    2114             :                     /*
    2115             :                      * For WITH CHECK OPTIONs coming from views, we might be
    2116             :                      * able to provide the details on the row, depending on
    2117             :                      * the permissions on the relation (that is, if the user
    2118             :                      * could view it directly anyway).  For RLS violations, we
    2119             :                      * don't include the data since we don't know if the user
    2120             :                      * should be able to view the tuple as that depends on the
    2121             :                      * USING policy.
    2122             :                      */
    2123             :                 case WCO_VIEW_CHECK:
    2124             :                     /* See the comment in ExecConstraints(). */
    2125          29 :                     if (resultRelInfo->ri_PartitionRoot)
    2126             :                     {
    2127           3 :                         HeapTuple   tuple = ExecFetchSlotTuple(slot);
    2128           3 :                         TupleDesc   old_tupdesc = RelationGetDescr(rel);
    2129             :                         TupleConversionMap *map;
    2130             : 
    2131           3 :                         rel = resultRelInfo->ri_PartitionRoot;
    2132           3 :                         tupdesc = RelationGetDescr(rel);
    2133             :                         /* a reverse map */
    2134           3 :                         map = convert_tuples_by_name(old_tupdesc, tupdesc,
    2135             :                                                      gettext_noop("could not convert row type"));
    2136           3 :                         if (map != NULL)
    2137             :                         {
    2138           2 :                             tuple = do_convert_tuple(tuple, map);
    2139           2 :                             ExecSetSlotDescriptor(slot, tupdesc);
    2140           2 :                             ExecStoreTuple(tuple, slot, InvalidBuffer, false);
    2141             :                         }
    2142             :                     }
    2143             : 
    2144          29 :                     insertedCols = GetInsertedColumns(resultRelInfo, estate);
    2145          29 :                     updatedCols = GetUpdatedColumns(resultRelInfo, estate);
    2146          29 :                     modifiedCols = bms_union(insertedCols, updatedCols);
    2147          29 :                     val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
    2148             :                                                              slot,
    2149             :                                                              tupdesc,
    2150             :                                                              modifiedCols,
    2151             :                                                              64);
    2152             : 
    2153          29 :                     ereport(ERROR,
    2154             :                             (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),
    2155             :                              errmsg("new row violates check option for view \"%s\"",
    2156             :                                     wco->relname),
    2157             :                              val_desc ? errdetail("Failing row contains %s.",
    2158             :                                                   val_desc) : 0));
    2159             :                     break;
    2160             :                 case WCO_RLS_INSERT_CHECK:
    2161             :                 case WCO_RLS_UPDATE_CHECK:
    2162          22 :                     if (wco->polname != NULL)
    2163           5 :                         ereport(ERROR,
    2164             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2165             :                                  errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
    2166             :                                         wco->polname, wco->relname)));
    2167             :                     else
    2168          17 :                         ereport(ERROR,
    2169             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2170             :                                  errmsg("new row violates row-level security policy for table \"%s\"",
    2171             :                                         wco->relname)));
    2172             :                     break;
    2173             :                 case WCO_RLS_CONFLICT_CHECK:
    2174           4 :                     if (wco->polname != NULL)
    2175           0 :                         ereport(ERROR,
    2176             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2177             :                                  errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
    2178             :                                         wco->polname, wco->relname)));
    2179             :                     else
    2180           4 :                         ereport(ERROR,
    2181             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2182             :                                  errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
    2183             :                                         wco->relname)));
    2184             :                     break;
    2185             :                 default:
    2186           0 :                     elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
    2187             :                     break;
    2188             :             }
    2189             :         }
    2190             :     }
    2191         186 : }
    2192             : 
    2193             : /*
    2194             :  * ExecBuildSlotValueDescription -- construct a string representing a tuple
    2195             :  *
    2196             :  * This is intentionally very similar to BuildIndexValueDescription, but
    2197             :  * unlike that function, we truncate long field values (to at most maxfieldlen
    2198             :  * bytes).  That seems necessary here since heap field values could be very
    2199             :  * long, whereas index entries typically aren't so wide.
    2200             :  *
    2201             :  * Also, unlike the case with index entries, we need to be prepared to ignore
    2202             :  * dropped columns.  We used to use the slot's tuple descriptor to decode the
    2203             :  * data, but the slot's descriptor doesn't identify dropped columns, so we
    2204             :  * now need to be passed the relation's descriptor.
    2205             :  *
    2206             :  * Note that, like BuildIndexValueDescription, if the user does not have
    2207             :  * permission to view any of the columns involved, a NULL is returned.  Unlike
    2208             :  * BuildIndexValueDescription, if the user has access to view a subset of the
    2209             :  * column involved, that subset will be returned with a key identifying which
    2210             :  * columns they are.
    2211             :  */
    2212             : static char *
    2213         125 : ExecBuildSlotValueDescription(Oid reloid,
    2214             :                               TupleTableSlot *slot,
    2215             :                               TupleDesc tupdesc,
    2216             :                               Bitmapset *modifiedCols,
    2217             :                               int maxfieldlen)
    2218             : {
    2219             :     StringInfoData buf;
    2220             :     StringInfoData collist;
    2221         125 :     bool        write_comma = false;
    2222         125 :     bool        write_comma_collist = false;
    2223             :     int         i;
    2224             :     AclResult   aclresult;
    2225         125 :     bool        table_perm = false;
    2226         125 :     bool        any_perm = false;
    2227             : 
    2228             :     /*
    2229             :      * Check if RLS is enabled and should be active for the relation; if so,
    2230             :      * then don't return anything.  Otherwise, go through normal permission
    2231             :      * checks.
    2232             :      */
    2233         125 :     if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
    2234           0 :         return NULL;
    2235             : 
    2236         125 :     initStringInfo(&buf);
    2237             : 
    2238         125 :     appendStringInfoChar(&buf, '(');
    2239             : 
    2240             :     /*
    2241             :      * Check if the user has permissions to see the row.  Table-level SELECT
    2242             :      * allows access to all columns.  If the user does not have table-level
    2243             :      * SELECT then we check each column and include those the user has SELECT
    2244             :      * rights on.  Additionally, we always include columns the user provided
    2245             :      * data for.
    2246             :      */
    2247         125 :     aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
    2248         125 :     if (aclresult != ACLCHECK_OK)
    2249             :     {
    2250             :         /* Set up the buffer for the column list */
    2251           5 :         initStringInfo(&collist);
    2252           5 :         appendStringInfoChar(&collist, '(');
    2253             :     }
    2254             :     else
    2255         120 :         table_perm = any_perm = true;
    2256             : 
    2257             :     /* Make sure the tuple is fully deconstructed */
    2258         125 :     slot_getallattrs(slot);
    2259             : 
    2260         420 :     for (i = 0; i < tupdesc->natts; i++)
    2261             :     {
    2262         295 :         bool        column_perm = false;
    2263             :         char       *val;
    2264             :         int         vallen;
    2265         295 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
    2266             : 
    2267             :         /* ignore dropped columns */
    2268         295 :         if (att->attisdropped)
    2269           2 :             continue;
    2270             : 
    2271         293 :         if (!table_perm)
    2272             :         {
    2273             :             /*
    2274             :              * No table-level SELECT, so need to make sure they either have
    2275             :              * SELECT rights on the column or that they have provided the data
    2276             :              * for the column.  If not, omit this column from the error
    2277             :              * message.
    2278             :              */
    2279          14 :             aclresult = pg_attribute_aclcheck(reloid, att->attnum,
    2280             :                                               GetUserId(), ACL_SELECT);
    2281          14 :             if (bms_is_member(att->attnum - FirstLowInvalidHeapAttributeNumber,
    2282           7 :                               modifiedCols) || aclresult == ACLCHECK_OK)
    2283             :             {
    2284           9 :                 column_perm = any_perm = true;
    2285             : 
    2286           9 :                 if (write_comma_collist)
    2287           4 :                     appendStringInfoString(&collist, ", ");
    2288             :                 else
    2289           5 :                     write_comma_collist = true;
    2290             : 
    2291           9 :                 appendStringInfoString(&collist, NameStr(att->attname));
    2292             :             }
    2293             :         }
    2294             : 
    2295         293 :         if (table_perm || column_perm)
    2296             :         {
    2297         288 :             if (slot->tts_isnull[i])
    2298          52 :                 val = "null";
    2299             :             else
    2300             :             {
    2301             :                 Oid         foutoid;
    2302             :                 bool        typisvarlena;
    2303             : 
    2304         236 :                 getTypeOutputInfo(att->atttypid,
    2305             :                                   &foutoid, &typisvarlena);
    2306         236 :                 val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
    2307             :             }
    2308             : 
    2309         288 :             if (write_comma)
    2310         163 :                 appendStringInfoString(&buf, ", ");
    2311             :             else
    2312         125 :                 write_comma = true;
    2313             : 
    2314             :             /* truncate if needed */
    2315         288 :             vallen = strlen(val);
    2316         288 :             if (vallen <= maxfieldlen)
    2317         288 :                 appendStringInfoString(&buf, val);
    2318             :             else
    2319             :             {
    2320           0 :                 vallen = pg_mbcliplen(val, vallen, maxfieldlen);
    2321           0 :                 appendBinaryStringInfo(&buf, val, vallen);
    2322           0 :                 appendStringInfoString(&buf, "...");
    2323             :             }
    2324             :         }
    2325             :     }
    2326             : 
    2327             :     /* If we end up with zero columns being returned, then return NULL. */
    2328         125 :     if (!any_perm)
    2329           0 :         return NULL;
    2330             : 
    2331         125 :     appendStringInfoChar(&buf, ')');
    2332             : 
    2333         125 :     if (!table_perm)
    2334             :     {
    2335           5 :         appendStringInfoString(&collist, ") = ");
    2336           5 :         appendStringInfoString(&collist, buf.data);
    2337             : 
    2338           5 :         return collist.data;
    2339             :     }
    2340             : 
    2341         120 :     return buf.data;
    2342             : }
    2343             : 
    2344             : 
    2345             : /*
    2346             :  * ExecUpdateLockMode -- find the appropriate UPDATE tuple lock mode for a
    2347             :  * given ResultRelInfo
    2348             :  */
    2349             : LockTupleMode
    2350         277 : ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
    2351             : {
    2352             :     Bitmapset  *keyCols;
    2353             :     Bitmapset  *updatedCols;
    2354             : 
    2355             :     /*
    2356             :      * Compute lock mode to use.  If columns that are part of the key have not
    2357             :      * been modified, then we can use a weaker lock, allowing for better
    2358             :      * concurrency.
    2359             :      */
    2360         277 :     updatedCols = GetUpdatedColumns(relinfo, estate);
    2361         277 :     keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
    2362             :                                          INDEX_ATTR_BITMAP_KEY);
    2363             : 
    2364         277 :     if (bms_overlap(keyCols, updatedCols))
    2365          16 :         return LockTupleExclusive;
    2366             : 
    2367         261 :     return LockTupleNoKeyExclusive;
    2368             : }
    2369             : 
    2370             : /*
    2371             :  * ExecFindRowMark -- find the ExecRowMark struct for given rangetable index
    2372             :  *
    2373             :  * If no such struct, either return NULL or throw error depending on missing_ok
    2374             :  */
    2375             : ExecRowMark *
    2376       18605 : ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
    2377             : {
    2378             :     ListCell   *lc;
    2379             : 
    2380       18965 :     foreach(lc, estate->es_rowMarks)
    2381             :     {
    2382        1463 :         ExecRowMark *erm = (ExecRowMark *) lfirst(lc);
    2383             : 
    2384        1463 :         if (erm->rti == rti)
    2385        1103 :             return erm;
    2386             :     }
    2387       17502 :     if (!missing_ok)
    2388           0 :         elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
    2389       17502 :     return NULL;
    2390             : }
    2391             : 
    2392             : /*
    2393             :  * ExecBuildAuxRowMark -- create an ExecAuxRowMark struct
    2394             :  *
    2395             :  * Inputs are the underlying ExecRowMark struct and the targetlist of the
    2396             :  * input plan node (not planstate node!).  We need the latter to find out
    2397             :  * the column numbers of the resjunk columns.
    2398             :  */
    2399             : ExecAuxRowMark *
    2400         600 : ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
    2401             : {
    2402         600 :     ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
    2403             :     char        resname[32];
    2404             : 
    2405         600 :     aerm->rowmark = erm;
    2406             : 
    2407             :     /* Look up the resjunk columns associated with this rowmark */
    2408         600 :     if (erm->markType != ROW_MARK_COPY)
    2409             :     {
    2410             :         /* need ctid for all methods other than COPY */
    2411         553 :         snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
    2412         553 :         aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
    2413             :                                                        resname);
    2414         553 :         if (!AttributeNumberIsValid(aerm->ctidAttNo))
    2415           0 :             elog(ERROR, "could not find junk %s column", resname);
    2416             :     }
    2417             :     else
    2418             :     {
    2419             :         /* need wholerow if COPY */
    2420          47 :         snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
    2421          47 :         aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
    2422             :                                                         resname);
    2423          47 :         if (!AttributeNumberIsValid(aerm->wholeAttNo))
    2424           0 :             elog(ERROR, "could not find junk %s column", resname);
    2425             :     }
    2426             : 
    2427             :     /* if child rel, need tableoid */
    2428         600 :     if (erm->rti != erm->prti)
    2429             :     {
    2430          56 :         snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
    2431          56 :         aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
    2432             :                                                        resname);
    2433          56 :         if (!AttributeNumberIsValid(aerm->toidAttNo))
    2434           0 :             elog(ERROR, "could not find junk %s column", resname);
    2435             :     }
    2436             : 
    2437         600 :     return aerm;
    2438             : }
    2439             : 
    2440             : 
    2441             : /*
    2442             :  * EvalPlanQual logic --- recheck modified tuple(s) to see if we want to
    2443             :  * process the updated version under READ COMMITTED rules.
    2444             :  *
    2445             :  * See backend/executor/README for some info about how this works.
    2446             :  */
    2447             : 
    2448             : 
    2449             : /*
    2450             :  * Check a modified tuple to see if we want to process its updated version
    2451             :  * under READ COMMITTED rules.
    2452             :  *
    2453             :  *  estate - outer executor state data
    2454             :  *  epqstate - state for EvalPlanQual rechecking
    2455             :  *  relation - table containing tuple
    2456             :  *  rti - rangetable index of table containing tuple
    2457             :  *  lockmode - requested tuple lock mode
    2458             :  *  *tid - t_ctid from the outdated tuple (ie, next updated version)
    2459             :  *  priorXmax - t_xmax from the outdated tuple
    2460             :  *
    2461             :  * *tid is also an output parameter: it's modified to hold the TID of the
    2462             :  * latest version of the tuple (note this may be changed even on failure)
    2463             :  *
    2464             :  * Returns a slot containing the new candidate update/delete tuple, or
    2465             :  * NULL if we determine we shouldn't process the row.
    2466             :  *
    2467             :  * Note: properly, lockmode should be declared as enum LockTupleMode,
    2468             :  * but we use "int" to avoid having to include heapam.h in executor.h.
    2469             :  */
    2470             : TupleTableSlot *
    2471           0 : EvalPlanQual(EState *estate, EPQState *epqstate,
    2472             :              Relation relation, Index rti, int lockmode,
    2473             :              ItemPointer tid, TransactionId priorXmax)
    2474             : {
    2475             :     TupleTableSlot *slot;
    2476             :     HeapTuple   copyTuple;
    2477             : 
    2478           0 :     Assert(rti > 0);
    2479             : 
    2480             :     /*
    2481             :      * Get and lock the updated version of the row; if fail, return NULL.
    2482             :      */
    2483           0 :     copyTuple = EvalPlanQualFetch(estate, relation, lockmode, LockWaitBlock,
    2484             :                                   tid, priorXmax);
    2485             : 
    2486           0 :     if (copyTuple == NULL)
    2487           0 :         return NULL;
    2488             : 
    2489             :     /*
    2490             :      * For UPDATE/DELETE we have to return tid of actual row we're executing
    2491             :      * PQ for.
    2492             :      */
    2493           0 :     *tid = copyTuple->t_self;
    2494             : 
    2495             :     /*
    2496             :      * Need to run a recheck subquery.  Initialize or reinitialize EPQ state.
    2497             :      */
    2498           0 :     EvalPlanQualBegin(epqstate, estate);
    2499             : 
    2500             :     /*
    2501             :      * Free old test tuple, if any, and store new tuple where relation's scan
    2502             :      * node will see it
    2503             :      */
    2504           0 :     EvalPlanQualSetTuple(epqstate, rti, copyTuple);
    2505             : 
    2506             :     /*
    2507             :      * Fetch any non-locked source rows
    2508             :      */
    2509           0 :     EvalPlanQualFetchRowMarks(epqstate);
    2510             : 
    2511             :     /*
    2512             :      * Run the EPQ query.  We assume it will return at most one tuple.
    2513             :      */
    2514           0 :     slot = EvalPlanQualNext(epqstate);
    2515             : 
    2516             :     /*
    2517             :      * If we got a tuple, force the slot to materialize the tuple so that it
    2518             :      * is not dependent on any local state in the EPQ query (in particular,
    2519             :      * it's highly likely that the slot contains references to any pass-by-ref
    2520             :      * datums that may be present in copyTuple).  As with the next step, this
    2521             :      * is to guard against early re-use of the EPQ query.
    2522             :      */
    2523           0 :     if (!TupIsNull(slot))
    2524           0 :         (void) ExecMaterializeSlot(slot);
    2525             : 
    2526             :     /*
    2527             :      * Clear out the test tuple.  This is needed in case the EPQ query is
    2528             :      * re-used to test a tuple for a different relation.  (Not clear that can
    2529             :      * really happen, but let's be safe.)
    2530             :      */
    2531           0 :     EvalPlanQualSetTuple(epqstate, rti, NULL);
    2532             : 
    2533           0 :     return slot;
    2534             : }
    2535             : 
    2536             : /*
    2537             :  * Fetch a copy of the newest version of an outdated tuple
    2538             :  *
    2539             :  *  estate - executor state data
    2540             :  *  relation - table containing tuple
    2541             :  *  lockmode - requested tuple lock mode
    2542             :  *  wait_policy - requested lock wait policy
    2543             :  *  *tid - t_ctid from the outdated tuple (ie, next updated version)
    2544             :  *  priorXmax - t_xmax from the outdated tuple
    2545             :  *
    2546             :  * Returns a palloc'd copy of the newest tuple version, or NULL if we find
    2547             :  * that there is no newest version (ie, the row was deleted not updated).
    2548             :  * We also return NULL if the tuple is locked and the wait policy is to skip
    2549             :  * such tuples.
    2550             :  *
    2551             :  * If successful, we have locked the newest tuple version, so caller does not
    2552             :  * need to worry about it changing anymore.
    2553             :  *
    2554             :  * Note: properly, lockmode should be declared as enum LockTupleMode,
    2555             :  * but we use "int" to avoid having to include heapam.h in executor.h.
    2556             :  */
    2557             : HeapTuple
    2558           0 : EvalPlanQualFetch(EState *estate, Relation relation, int lockmode,
    2559             :                   LockWaitPolicy wait_policy,
    2560             :                   ItemPointer tid, TransactionId priorXmax)
    2561             : {
    2562           0 :     HeapTuple   copyTuple = NULL;
    2563             :     HeapTupleData tuple;
    2564             :     SnapshotData SnapshotDirty;
    2565             : 
    2566             :     /*
    2567             :      * fetch target tuple
    2568             :      *
    2569             :      * Loop here to deal with updated or busy tuples
    2570             :      */
    2571           0 :     InitDirtySnapshot(SnapshotDirty);
    2572           0 :     tuple.t_self = *tid;
    2573             :     for (;;)
    2574             :     {
    2575             :         Buffer      buffer;
    2576             : 
    2577           0 :         if (heap_fetch(relation, &SnapshotDirty, &tuple, &buffer, true, NULL))
    2578             :         {
    2579             :             HTSU_Result test;
    2580             :             HeapUpdateFailureData hufd;
    2581             : 
    2582             :             /*
    2583             :              * If xmin isn't what we're expecting, the slot must have been
    2584             :              * recycled and reused for an unrelated tuple.  This implies that
    2585             :              * the latest version of the row was deleted, so we need do
    2586             :              * nothing.  (Should be safe to examine xmin without getting
    2587             :              * buffer's content lock.  We assume reading a TransactionId to be
    2588             :              * atomic, and Xmin never changes in an existing tuple, except to
    2589             :              * invalid or frozen, and neither of those can match priorXmax.)
    2590             :              */
    2591           0 :             if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data),
    2592             :                                      priorXmax))
    2593             :             {
    2594           0 :                 ReleaseBuffer(buffer);
    2595           0 :                 return NULL;
    2596             :             }
    2597             : 
    2598             :             /* otherwise xmin should not be dirty... */
    2599           0 :             if (TransactionIdIsValid(SnapshotDirty.xmin))
    2600           0 :                 elog(ERROR, "t_xmin is uncommitted in tuple to be updated");
    2601             : 
    2602             :             /*
    2603             :              * If tuple is being updated by other transaction then we have to
    2604             :              * wait for its commit/abort, or die trying.
    2605             :              */
    2606           0 :             if (TransactionIdIsValid(SnapshotDirty.xmax))
    2607             :             {
    2608           0 :                 ReleaseBuffer(buffer);
    2609           0 :                 switch (wait_policy)
    2610             :                 {
    2611             :                     case LockWaitBlock:
    2612           0 :                         XactLockTableWait(SnapshotDirty.xmax,
    2613             :                                           relation, &tuple.t_self,
    2614             :                                           XLTW_FetchUpdated);
    2615           0 :                         break;
    2616             :                     case LockWaitSkip:
    2617           0 :                         if (!ConditionalXactLockTableWait(SnapshotDirty.xmax))
    2618           0 :                             return NULL;    /* skip instead of waiting */
    2619           0 :                         break;
    2620             :                     case LockWaitError:
    2621           0 :                         if (!ConditionalXactLockTableWait(SnapshotDirty.xmax))
    2622           0 :                             ereport(ERROR,
    2623             :                                     (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
    2624             :                                      errmsg("could not obtain lock on row in relation \"%s\"",
    2625             :                                             RelationGetRelationName(relation))));
    2626           0 :                         break;
    2627             :                 }
    2628           0 :                 continue;       /* loop back to repeat heap_fetch */
    2629             :             }
    2630             : 
    2631             :             /*
    2632             :              * If tuple was inserted by our own transaction, we have to check
    2633             :              * cmin against es_output_cid: cmin >= current CID means our
    2634             :              * command cannot see the tuple, so we should ignore it. Otherwise
    2635             :              * heap_lock_tuple() will throw an error, and so would any later
    2636             :              * attempt to update or delete the tuple.  (We need not check cmax
    2637             :              * because HeapTupleSatisfiesDirty will consider a tuple deleted
    2638             :              * by our transaction dead, regardless of cmax.) We just checked
    2639             :              * that priorXmax == xmin, so we can test that variable instead of
    2640             :              * doing HeapTupleHeaderGetXmin again.
    2641             :              */
    2642           0 :             if (TransactionIdIsCurrentTransactionId(priorXmax) &&
    2643           0 :                 HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid)
    2644             :             {
    2645           0 :                 ReleaseBuffer(buffer);
    2646           0 :                 return NULL;
    2647             :             }
    2648             : 
    2649             :             /*
    2650             :              * This is a live tuple, so now try to lock it.
    2651             :              */
    2652           0 :             test = heap_lock_tuple(relation, &tuple,
    2653             :                                    estate->es_output_cid,
    2654             :                                    lockmode, wait_policy,
    2655             :                                    false, &buffer, &hufd);
    2656             :             /* We now have two pins on the buffer, get rid of one */
    2657           0 :             ReleaseBuffer(buffer);
    2658             : 
    2659           0 :             switch (test)
    2660             :             {
    2661             :                 case HeapTupleSelfUpdated:
    2662             : 
    2663             :                     /*
    2664             :                      * The target tuple was already updated or deleted by the
    2665             :                      * current command, or by a later command in the current
    2666             :                      * transaction.  We *must* ignore the tuple in the former
    2667             :                      * case, so as to avoid the "Halloween problem" of
    2668             :                      * repeated update attempts.  In the latter case it might
    2669             :                      * be sensible to fetch the updated tuple instead, but
    2670             :                      * doing so would require changing heap_update and
    2671             :                      * heap_delete to not complain about updating "invisible"
    2672             :                      * tuples, which seems pretty scary (heap_lock_tuple will
    2673             :                      * not complain, but few callers expect
    2674             :                      * HeapTupleInvisible, and we're not one of them).  So for
    2675             :                      * now, treat the tuple as deleted and do not process.
    2676             :                      */
    2677           0 :                     ReleaseBuffer(buffer);
    2678           0 :                     return NULL;
    2679             : 
    2680             :                 case HeapTupleMayBeUpdated:
    2681             :                     /* successfully locked */
    2682           0 :                     break;
    2683             : 
    2684             :                 case HeapTupleUpdated:
    2685           0 :                     ReleaseBuffer(buffer);
    2686           0 :                     if (IsolationUsesXactSnapshot())
    2687           0 :                         ereport(ERROR,
    2688             :                                 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
    2689             :                                  errmsg("could not serialize access due to concurrent update")));
    2690             : 
    2691             :                     /* Should not encounter speculative tuple on recheck */
    2692           0 :                     Assert(!HeapTupleHeaderIsSpeculative(tuple.t_data));
    2693           0 :                     if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
    2694             :                     {
    2695             :                         /* it was updated, so look at the updated version */
    2696           0 :                         tuple.t_self = hufd.ctid;
    2697             :                         /* updated row should have xmin matching this xmax */
    2698           0 :                         priorXmax = hufd.xmax;
    2699           0 :                         continue;
    2700             :                     }
    2701             :                     /* tuple was deleted, so give up */
    2702           0 :                     return NULL;
    2703             : 
    2704             :                 case HeapTupleWouldBlock:
    2705           0 :                     ReleaseBuffer(buffer);
    2706           0 :                     return NULL;
    2707             : 
    2708             :                 case HeapTupleInvisible:
    2709           0 :                     elog(ERROR, "attempted to lock invisible tuple");
    2710             : 
    2711             :                 default:
    2712           0 :                     ReleaseBuffer(buffer);
    2713           0 :                     elog(ERROR, "unrecognized heap_lock_tuple status: %u",
    2714             :                          test);
    2715             :                     return NULL;    /* keep compiler quiet */
    2716             :             }
    2717             : 
    2718             :             /*
    2719             :              * We got tuple - now copy it for use by recheck query.
    2720             :              */
    2721           0 :             copyTuple = heap_copytuple(&tuple);
    2722           0 :             ReleaseBuffer(buffer);
    2723           0 :             break;
    2724             :         }
    2725             : 
    2726             :         /*
    2727             :          * If the referenced slot was actually empty, the latest version of
    2728             :          * the row must have been deleted, so we need do nothing.
    2729             :          */
    2730           0 :         if (tuple.t_data == NULL)
    2731             :         {
    2732           0 :             ReleaseBuffer(buffer);
    2733           0 :             return NULL;
    2734             :         }
    2735             : 
    2736             :         /*
    2737             :          * As above, if xmin isn't what we're expecting, do nothing.
    2738             :          */
    2739           0 :         if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data),
    2740             :                                  priorXmax))
    2741             :         {
    2742           0 :             ReleaseBuffer(buffer);
    2743           0 :             return NULL;
    2744             :         }
    2745             : 
    2746             :         /*
    2747             :          * If we get here, the tuple was found but failed SnapshotDirty.
    2748             :          * Assuming the xmin is either a committed xact or our own xact (as it
    2749             :          * certainly should be if we're trying to modify the tuple), this must
    2750             :          * mean that the row was updated or deleted by either a committed xact
    2751             :          * or our own xact.  If it was deleted, we can ignore it; if it was
    2752             :          * updated then chain up to the next version and repeat the whole
    2753             :          * process.
    2754             :          *
    2755             :          * As above, it should be safe to examine xmax and t_ctid without the
    2756             :          * buffer content lock, because they can't be changing.
    2757             :          */
    2758           0 :         if (ItemPointerEquals(&tuple.t_self, &tuple.t_data->t_ctid))
    2759             :         {
    2760             :             /* deleted, so forget about it */
    2761           0 :             ReleaseBuffer(buffer);
    2762           0 :             return NULL;
    2763             :         }
    2764             : 
    2765             :         /* updated, so look at the updated row */
    2766           0 :         tuple.t_self = tuple.t_data->t_ctid;
    2767             :         /* updated row should have xmin matching this xmax */
    2768           0 :         priorXmax = HeapTupleHeaderGetUpdateXid(tuple.t_data);
    2769           0 :         ReleaseBuffer(buffer);
    2770             :         /* loop back to fetch next in chain */
    2771           0 :     }
    2772             : 
    2773             :     /*
    2774             :      * Return the copied tuple
    2775             :      */
    2776           0 :     return copyTuple;
    2777             : }
    2778             : 
    2779             : /*
    2780             :  * EvalPlanQualInit -- initialize during creation of a plan state node
    2781             :  * that might need to invoke EPQ processing.
    2782             :  *
    2783             :  * Note: subplan/auxrowmarks can be NULL/NIL if they will be set later
    2784             :  * with EvalPlanQualSetPlan.
    2785             :  */
    2786             : void
    2787        4847 : EvalPlanQualInit(EPQState *epqstate, EState *estate,
    2788             :                  Plan *subplan, List *auxrowmarks, int epqParam)
    2789             : {
    2790             :     /* Mark the EPQ state inactive */
    2791        4847 :     epqstate->estate = NULL;
    2792        4847 :     epqstate->planstate = NULL;
    2793        4847 :     epqstate->origslot = NULL;
    2794             :     /* ... and remember data that EvalPlanQualBegin will need */
    2795        4847 :     epqstate->plan = subplan;
    2796        4847 :     epqstate->arowMarks = auxrowmarks;
    2797        4847 :     epqstate->epqParam = epqParam;
    2798        4847 : }
    2799             : 
    2800             : /*
    2801             :  * EvalPlanQualSetPlan -- set or change subplan of an EPQState.
    2802             :  *
    2803             :  * We need this so that ModifyTable can deal with multiple subplans.
    2804             :  */
    2805             : void
    2806        4575 : EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
    2807             : {
    2808             :     /* If we have a live EPQ query, shut it down */
    2809        4575 :     EvalPlanQualEnd(epqstate);
    2810             :     /* And set/change the plan pointer */
    2811        4575 :     epqstate->plan = subplan;
    2812             :     /* The rowmarks depend on the plan, too */
    2813        4575 :     epqstate->arowMarks = auxrowmarks;
    2814        4575 : }
    2815             : 
    2816             : /*
    2817             :  * Install one test tuple into EPQ state, or clear test tuple if tuple == NULL
    2818             :  *
    2819             :  * NB: passed tuple must be palloc'd; it may get freed later
    2820             :  */
    2821             : void
    2822           0 : EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
    2823             : {
    2824           0 :     EState     *estate = epqstate->estate;
    2825             : 
    2826           0 :     Assert(rti > 0);
    2827             : 
    2828             :     /*
    2829             :      * free old test tuple, if any, and store new tuple where relation's scan
    2830             :      * node will see it
    2831             :      */
    2832           0 :     if (estate->es_epqTuple[rti - 1] != NULL)
    2833           0 :         heap_freetuple(estate->es_epqTuple[rti - 1]);
    2834           0 :     estate->es_epqTuple[rti - 1] = tuple;
    2835           0 :     estate->es_epqTupleSet[rti - 1] = true;
    2836           0 : }
    2837             : 
    2838             : /*
    2839             :  * Fetch back the current test tuple (if any) for the specified RTI
    2840             :  */
    2841             : HeapTuple
    2842           0 : EvalPlanQualGetTuple(EPQState *epqstate, Index rti)
    2843             : {
    2844           0 :     EState     *estate = epqstate->estate;
    2845             : 
    2846           0 :     Assert(rti > 0);
    2847             : 
    2848           0 :     return estate->es_epqTuple[rti - 1];
    2849             : }
    2850             : 
    2851             : /*
    2852             :  * Fetch the current row values for any non-locked relations that need
    2853             :  * to be scanned by an EvalPlanQual operation.  origslot must have been set
    2854             :  * to contain the current result row (top-level row) that we need to recheck.
    2855             :  */
    2856             : void
    2857           0 : EvalPlanQualFetchRowMarks(EPQState *epqstate)
    2858             : {
    2859             :     ListCell   *l;
    2860             : 
    2861           0 :     Assert(epqstate->origslot != NULL);
    2862             : 
    2863           0 :     foreach(l, epqstate->arowMarks)
    2864             :     {
    2865           0 :         ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
    2866           0 :         ExecRowMark *erm = aerm->rowmark;
    2867             :         Datum       datum;
    2868             :         bool        isNull;
    2869             :         HeapTupleData tuple;
    2870             : 
    2871           0 :         if (RowMarkRequiresRowShareLock(erm->markType))
    2872           0 :             elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
    2873             : 
    2874             :         /* clear any leftover test tuple for this rel */
    2875           0 :         EvalPlanQualSetTuple(epqstate, erm->rti, NULL);
    2876             : 
    2877             :         /* if child rel, must check whether it produced this row */
    2878           0 :         if (erm->rti != erm->prti)
    2879             :         {
    2880             :             Oid         tableoid;
    2881             : 
    2882           0 :             datum = ExecGetJunkAttribute(epqstate->origslot,
    2883           0 :                                          aerm->toidAttNo,
    2884             :                                          &isNull);
    2885             :             /* non-locked rels could be on the inside of outer joins */
    2886           0 :             if (isNull)
    2887           0 :                 continue;
    2888           0 :             tableoid = DatumGetObjectId(datum);
    2889             : 
    2890           0 :             Assert(OidIsValid(erm->relid));
    2891           0 :             if (tableoid != erm->relid)
    2892             :             {
    2893             :                 /* this child is inactive right now */
    2894           0 :                 continue;
    2895             :             }
    2896             :         }
    2897             : 
    2898           0 :         if (erm->markType == ROW_MARK_REFERENCE)
    2899             :         {
    2900             :             HeapTuple   copyTuple;
    2901             : 
    2902           0 :             Assert(erm->relation != NULL);
    2903             : 
    2904             :             /* fetch the tuple's ctid */
    2905           0 :             datum = ExecGetJunkAttribute(epqstate->origslot,
    2906           0 :                                          aerm->ctidAttNo,
    2907             :                                          &isNull);
    2908             :             /* non-locked rels could be on the inside of outer joins */
    2909           0 :             if (isNull)
    2910           0 :                 continue;
    2911             : 
    2912             :             /* fetch requests on foreign tables must be passed to their FDW */
    2913           0 :             if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
    2914             :             {
    2915             :                 FdwRoutine *fdwroutine;
    2916           0 :                 bool        updated = false;
    2917             : 
    2918           0 :                 fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
    2919             :                 /* this should have been checked already, but let's be safe */
    2920           0 :                 if (fdwroutine->RefetchForeignRow == NULL)
    2921           0 :                     ereport(ERROR,
    2922             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2923             :                              errmsg("cannot lock rows in foreign table \"%s\"",
    2924             :                                     RelationGetRelationName(erm->relation))));
    2925           0 :                 copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate,
    2926             :                                                           erm,
    2927             :                                                           datum,
    2928             :                                                           &updated);
    2929           0 :                 if (copyTuple == NULL)
    2930           0 :                     elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
    2931             : 
    2932             :                 /*
    2933             :                  * Ideally we'd insist on updated == false here, but that
    2934             :                  * assumes that FDWs can track that exactly, which they might
    2935             :                  * not be able to.  So just ignore the flag.
    2936             :                  */
    2937             :             }
    2938             :             else
    2939             :             {
    2940             :                 /* ordinary table, fetch the tuple */
    2941             :                 Buffer      buffer;
    2942             : 
    2943           0 :                 tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
    2944           0 :                 if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
    2945             :                                 false, NULL))
    2946           0 :                     elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
    2947             : 
    2948             :                 /* successful, copy tuple */
    2949           0 :                 copyTuple = heap_copytuple(&tuple);
    2950           0 :                 ReleaseBuffer(buffer);
    2951             :             }
    2952             : 
    2953             :             /* store tuple */
    2954           0 :             EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
    2955             :         }
    2956             :         else
    2957             :         {
    2958             :             HeapTupleHeader td;
    2959             : 
    2960           0 :             Assert(erm->markType == ROW_MARK_COPY);
    2961             : 
    2962             :             /* fetch the whole-row Var for the relation */
    2963           0 :             datum = ExecGetJunkAttribute(epqstate->origslot,
    2964           0 :                                          aerm->wholeAttNo,
    2965             :                                          &isNull);
    2966             :             /* non-locked rels could be on the inside of outer joins */
    2967           0 :             if (isNull)
    2968           0 :                 continue;
    2969           0 :             td = DatumGetHeapTupleHeader(datum);
    2970             : 
    2971             :             /* build a temporary HeapTuple control structure */
    2972           0 :             tuple.t_len = HeapTupleHeaderGetDatumLength(td);
    2973           0 :             tuple.t_data = td;
    2974             :             /* relation might be a foreign table, if so provide tableoid */
    2975           0 :             tuple.t_tableOid = erm->relid;
    2976             :             /* also copy t_ctid in case there's valid data there */
    2977           0 :             tuple.t_self = td->t_ctid;
    2978             : 
    2979             :             /* copy and store tuple */
    2980           0 :             EvalPlanQualSetTuple(epqstate, erm->rti,
    2981             :                                  heap_copytuple(&tuple));
    2982             :         }
    2983             :     }
    2984           0 : }
    2985             : 
    2986             : /*
    2987             :  * Fetch the next row (if any) from EvalPlanQual testing
    2988             :  *
    2989             :  * (In practice, there should never be more than one row...)
    2990             :  */
    2991             : TupleTableSlot *
    2992           0 : EvalPlanQualNext(EPQState *epqstate)
    2993             : {
    2994             :     MemoryContext oldcontext;
    2995             :     TupleTableSlot *slot;
    2996             : 
    2997           0 :     oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
    2998           0 :     slot = ExecProcNode(epqstate->planstate);
    2999           0 :     MemoryContextSwitchTo(oldcontext);
    3000             : 
    3001           0 :     return slot;
    3002             : }
    3003             : 
    3004             : /*
    3005             :  * Initialize or reset an EvalPlanQual state tree
    3006             :  */
    3007             : void
    3008           0 : EvalPlanQualBegin(EPQState *epqstate, EState *parentestate)
    3009             : {
    3010           0 :     EState     *estate = epqstate->estate;
    3011             : 
    3012           0 :     if (estate == NULL)
    3013             :     {
    3014             :         /* First time through, so create a child EState */
    3015           0 :         EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
    3016             :     }
    3017             :     else
    3018             :     {
    3019             :         /*
    3020             :          * We already have a suitable child EPQ tree, so just reset it.
    3021             :          */
    3022           0 :         int         rtsize = list_length(parentestate->es_range_table);
    3023           0 :         PlanState  *planstate = epqstate->planstate;
    3024             : 
    3025           0 :         MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
    3026             : 
    3027             :         /* Recopy current values of parent parameters */
    3028           0 :         if (parentestate->es_plannedstmt->nParamExec > 0)
    3029             :         {
    3030           0 :             int         i = parentestate->es_plannedstmt->nParamExec;
    3031             : 
    3032           0 :             while (--i >= 0)
    3033             :             {
    3034             :                 /* copy value if any, but not execPlan link */
    3035           0 :                 estate->es_param_exec_vals[i].value =
    3036           0 :                     parentestate->es_param_exec_vals[i].value;
    3037           0 :                 estate->es_param_exec_vals[i].isnull =
    3038           0 :                     parentestate->es_param_exec_vals[i].isnull;
    3039             :             }
    3040             :         }
    3041             : 
    3042             :         /*
    3043             :          * Mark child plan tree as needing rescan at all scan nodes.  The
    3044             :          * first ExecProcNode will take care of actually doing the rescan.
    3045             :          */
    3046           0 :         planstate->chgParam = bms_add_member(planstate->chgParam,
    3047             :                                              epqstate->epqParam);
    3048             :     }
    3049           0 : }
    3050             : 
    3051             : /*
    3052             :  * Start execution of an EvalPlanQual plan tree.
    3053             :  *
    3054             :  * This is a cut-down version of ExecutorStart(): we copy some state from
    3055             :  * the top-level estate rather than initializing it fresh.
    3056             :  */
    3057             : static void
    3058           0 : EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
    3059             : {
    3060             :     EState     *estate;
    3061             :     int         rtsize;
    3062             :     MemoryContext oldcontext;
    3063             :     ListCell   *l;
    3064             : 
    3065           0 :     rtsize = list_length(parentestate->es_range_table);
    3066             : 
    3067           0 :     epqstate->estate = estate = CreateExecutorState();
    3068             : 
    3069           0 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    3070             : 
    3071             :     /*
    3072             :      * Child EPQ EStates share the parent's copy of unchanging state such as
    3073             :      * the snapshot, rangetable, result-rel info, and external Param info.
    3074             :      * They need their own copies of local state, including a tuple table,
    3075             :      * es_param_exec_vals, etc.
    3076             :      *
    3077             :      * The ResultRelInfo array management is trickier than it looks.  We
    3078             :      * create a fresh array for the child but copy all the content from the
    3079             :      * parent.  This is because it's okay for the child to share any
    3080             :      * per-relation state the parent has already created --- but if the child
    3081             :      * sets up any ResultRelInfo fields, such as its own junkfilter, that
    3082             :      * state must *not* propagate back to the parent.  (For one thing, the
    3083             :      * pointed-to data is in a memory context that won't last long enough.)
    3084             :      */
    3085           0 :     estate->es_direction = ForwardScanDirection;
    3086           0 :     estate->es_snapshot = parentestate->es_snapshot;
    3087           0 :     estate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
    3088           0 :     estate->es_range_table = parentestate->es_range_table;
    3089           0 :     estate->es_plannedstmt = parentestate->es_plannedstmt;
    3090           0 :     estate->es_junkFilter = parentestate->es_junkFilter;
    3091           0 :     estate->es_output_cid = parentestate->es_output_cid;
    3092           0 :     if (parentestate->es_num_result_relations > 0)
    3093             :     {
    3094           0 :         int         numResultRelations = parentestate->es_num_result_relations;
    3095             :         ResultRelInfo *resultRelInfos;
    3096             : 
    3097           0 :         resultRelInfos = (ResultRelInfo *)
    3098           0 :             palloc(numResultRelations * sizeof(ResultRelInfo));
    3099           0 :         memcpy(resultRelInfos, parentestate->es_result_relations,
    3100             :                numResultRelations * sizeof(ResultRelInfo));
    3101           0 :         estate->es_result_relations = resultRelInfos;
    3102           0 :         estate->es_num_result_relations = numResultRelations;
    3103             :     }
    3104             :     /* es_result_relation_info must NOT be copied */
    3105             :     /* es_trig_target_relations must NOT be copied */
    3106           0 :     estate->es_rowMarks = parentestate->es_rowMarks;
    3107           0 :     estate->es_top_eflags = parentestate->es_top_eflags;
    3108           0 :     estate->es_instrument = parentestate->es_instrument;
    3109             :     /* es_auxmodifytables must NOT be copied */
    3110             : 
    3111             :     /*
    3112             :      * The external param list is simply shared from parent.  The internal
    3113             :      * param workspace has to be local state, but we copy the initial values
    3114             :      * from the parent, so as to have access to any param values that were
    3115             :      * already set from other parts of the parent's plan tree.
    3116             :      */
    3117           0 :     estate->es_param_list_info = parentestate->es_param_list_info;
    3118           0 :     if (parentestate->es_plannedstmt->nParamExec > 0)
    3119             :     {
    3120           0 :         int         i = parentestate->es_plannedstmt->nParamExec;
    3121             : 
    3122           0 :         estate->es_param_exec_vals = (ParamExecData *)
    3123           0 :             palloc0(i * sizeof(ParamExecData));
    3124           0 :         while (--i >= 0)
    3125             :         {
    3126             :             /* copy value if any, but not execPlan link */
    3127           0 :             estate->es_param_exec_vals[i].value =
    3128           0 :                 parentestate->es_param_exec_vals[i].value;
    3129           0 :             estate->es_param_exec_vals[i].isnull =
    3130           0 :                 parentestate->es_param_exec_vals[i].isnull;
    3131             :         }
    3132             :     }
    3133             : 
    3134             :     /*
    3135             :      * Each EState must have its own es_epqScanDone state, but if we have
    3136             :      * nested EPQ checks they should share es_epqTuple arrays.  This allows
    3137             :      * sub-rechecks to inherit the values being examined by an outer recheck.
    3138             :      */
    3139           0 :     estate->es_epqScanDone = (bool *) palloc0(rtsize * sizeof(bool));
    3140           0 :     if (parentestate->es_epqTuple != NULL)
    3141             :     {
    3142           0 :         estate->es_epqTuple = parentestate->es_epqTuple;
    3143           0 :         estate->es_epqTupleSet = parentestate->es_epqTupleSet;
    3144             :     }
    3145             :     else
    3146             :     {
    3147           0 :         estate->es_epqTuple = (HeapTuple *)
    3148           0 :             palloc0(rtsize * sizeof(HeapTuple));
    3149           0 :         estate->es_epqTupleSet = (bool *)
    3150           0 :             palloc0(rtsize * sizeof(bool));
    3151             :     }
    3152             : 
    3153             :     /*
    3154             :      * Each estate also has its own tuple table.
    3155             :      */
    3156           0 :     estate->es_tupleTable = NIL;
    3157             : 
    3158             :     /*
    3159             :      * Initialize private state information for each SubPlan.  We must do this
    3160             :      * before running ExecInitNode on the main query tree, since
    3161             :      * ExecInitSubPlan expects to be able to find these entries. Some of the
    3162             :      * SubPlans might not be used in the part of the plan tree we intend to
    3163             :      * run, but since it's not easy to tell which, we just initialize them
    3164             :      * all.
    3165             :      */
    3166           0 :     Assert(estate->es_subplanstates == NIL);
    3167           0 :     foreach(l, parentestate->es_plannedstmt->subplans)
    3168             :     {
    3169           0 :         Plan       *subplan = (Plan *) lfirst(l);
    3170             :         PlanState  *subplanstate;
    3171             : 
    3172           0 :         subplanstate = ExecInitNode(subplan, estate, 0);
    3173           0 :         estate->es_subplanstates = lappend(estate->es_subplanstates,
    3174             :                                            subplanstate);
    3175             :     }
    3176             : 
    3177             :     /*
    3178             :      * Initialize the private state information for all the nodes in the part
    3179             :      * of the plan tree we need to run.  This opens files, allocates storage
    3180             :      * and leaves us ready to start processing tuples.
    3181             :      */
    3182           0 :     epqstate->planstate = ExecInitNode(planTree, estate, 0);
    3183             : 
    3184           0 :     MemoryContextSwitchTo(oldcontext);
    3185           0 : }
    3186             : 
    3187             : /*
    3188             :  * EvalPlanQualEnd -- shut down at termination of parent plan state node,
    3189             :  * or if we are done with the current EPQ child.
    3190             :  *
    3191             :  * This is a cut-down version of ExecutorEnd(); basically we want to do most
    3192             :  * of the normal cleanup, but *not* close result relations (which we are
    3193             :  * just sharing from the outer query).  We do, however, have to close any
    3194             :  * trigger target relations that got opened, since those are not shared.
    3195             :  * (There probably shouldn't be any of the latter, but just in case...)
    3196             :  */
    3197             : void
    3198        9095 : EvalPlanQualEnd(EPQState *epqstate)
    3199             : {
    3200        9095 :     EState     *estate = epqstate->estate;
    3201             :     MemoryContext oldcontext;
    3202             :     ListCell   *l;
    3203             : 
    3204        9095 :     if (estate == NULL)
    3205       18190 :         return;                 /* idle, so nothing to do */
    3206             : 
    3207           0 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    3208             : 
    3209           0 :     ExecEndNode(epqstate->planstate);
    3210             : 
    3211           0 :     foreach(l, estate->es_subplanstates)
    3212             :     {
    3213           0 :         PlanState  *subplanstate = (PlanState *) lfirst(l);
    3214             : 
    3215           0 :         ExecEndNode(subplanstate);
    3216             :     }
    3217             : 
    3218             :     /* throw away the per-estate tuple table */
    3219           0 :     ExecResetTupleTable(estate->es_tupleTable, false);
    3220             : 
    3221             :     /* close any trigger target relations attached to this EState */
    3222           0 :     ExecCleanUpTriggerState(estate);
    3223             : 
    3224           0 :     MemoryContextSwitchTo(oldcontext);
    3225             : 
    3226           0 :     FreeExecutorState(estate);
    3227             : 
    3228             :     /* Mark EPQState idle */
    3229           0 :     epqstate->estate = NULL;
    3230           0 :     epqstate->planstate = NULL;
    3231           0 :     epqstate->origslot = NULL;
    3232             : }
    3233             : 
    3234             : /*
    3235             :  * ExecSetupPartitionTupleRouting - set up information needed during
    3236             :  * tuple routing for partitioned tables
    3237             :  *
    3238             :  * Output arguments:
    3239             :  * 'pd' receives an array of PartitionDispatch objects with one entry for
    3240             :  *      every partitioned table in the partition tree
    3241             :  * 'partitions' receives an array of ResultRelInfo objects with one entry for
    3242             :  *      every leaf partition in the partition tree
    3243             :  * 'tup_conv_maps' receives an array of TupleConversionMap objects with one
    3244             :  *      entry for every leaf partition (required to convert input tuple based
    3245             :  *      on the root table's rowtype to a leaf partition's rowtype after tuple
    3246             :  *      routing is done)
    3247             :  * 'partition_tuple_slot' receives a standalone TupleTableSlot to be used
    3248             :  *      to manipulate any given leaf partition's rowtype after that partition
    3249             :  *      is chosen by tuple-routing.
    3250             :  * 'num_parted' receives the number of partitioned tables in the partition
    3251             :  *      tree (= the number of entries in the 'pd' output array)
    3252             :  * 'num_partitions' receives the number of leaf partitions in the partition
    3253             :  *      tree (= the number of entries in the 'partitions' and 'tup_conv_maps'
    3254             :  *      output arrays
    3255             :  *
    3256             :  * Note that all the relations in the partition tree are locked using the
    3257             :  * RowExclusiveLock mode upon return from this function.
    3258             :  */
    3259             : void
    3260          69 : ExecSetupPartitionTupleRouting(Relation rel,
    3261             :                                Index resultRTindex,
    3262             :                                EState *estate,
    3263             :                                PartitionDispatch **pd,
    3264             :                                ResultRelInfo **partitions,
    3265             :                                TupleConversionMap ***tup_conv_maps,
    3266             :                                TupleTableSlot **partition_tuple_slot,
    3267             :                                int *num_parted, int *num_partitions)
    3268             : {
    3269          69 :     TupleDesc   tupDesc = RelationGetDescr(rel);
    3270             :     List       *leaf_parts;
    3271             :     ListCell   *cell;
    3272             :     int         i;
    3273             :     ResultRelInfo *leaf_part_rri;
    3274             : 
    3275             :     /*
    3276             :      * Get the information about the partition tree after locking all the
    3277             :      * partitions.
    3278             :      */
    3279          69 :     (void) find_all_inheritors(RelationGetRelid(rel), RowExclusiveLock, NULL);
    3280          69 :     *pd = RelationGetPartitionDispatchInfo(rel, num_parted, &leaf_parts);
    3281          69 :     *num_partitions = list_length(leaf_parts);
    3282          69 :     *partitions = (ResultRelInfo *) palloc(*num_partitions *
    3283             :                                            sizeof(ResultRelInfo));
    3284          69 :     *tup_conv_maps = (TupleConversionMap **) palloc0(*num_partitions *
    3285             :                                                      sizeof(TupleConversionMap *));
    3286             : 
    3287             :     /*
    3288             :      * Initialize an empty slot that will be used to manipulate tuples of any
    3289             :      * given partition's rowtype.  It is attached to the caller-specified node
    3290             :      * (such as ModifyTableState) and released when the node finishes
    3291             :      * processing.
    3292             :      */
    3293          69 :     *partition_tuple_slot = MakeTupleTableSlot();
    3294             : 
    3295          69 :     leaf_part_rri = *partitions;
    3296          69 :     i = 0;
    3297         301 :     foreach(cell, leaf_parts)
    3298             :     {
    3299             :         Relation    partrel;
    3300             :         TupleDesc   part_tupdesc;
    3301             : 
    3302             :         /*
    3303             :          * We locked all the partitions above including the leaf partitions.
    3304             :          * Note that each of the relations in *partitions are eventually
    3305             :          * closed by the caller.
    3306             :          */
    3307         232 :         partrel = heap_open(lfirst_oid(cell), NoLock);
    3308         232 :         part_tupdesc = RelationGetDescr(partrel);
    3309             : 
    3310             :         /*
    3311             :          * Verify result relation is a valid target for the current operation.
    3312             :          */
    3313         232 :         CheckValidResultRel(partrel, CMD_INSERT);
    3314             : 
    3315             :         /*
    3316             :          * Save a tuple conversion map to convert a tuple routed to this
    3317             :          * partition from the parent's type to the partition's.
    3318             :          */
    3319         232 :         (*tup_conv_maps)[i] = convert_tuples_by_name(tupDesc, part_tupdesc,
    3320             :                                                      gettext_noop("could not convert row type"));
    3321             : 
    3322         232 :         InitResultRelInfo(leaf_part_rri,
    3323             :                           partrel,
    3324             :                           resultRTindex,
    3325             :                           rel,
    3326             :                           estate->es_instrument);
    3327             : 
    3328         232 :         estate->es_leaf_result_relations =
    3329         232 :             lappend(estate->es_leaf_result_relations, leaf_part_rri);
    3330             : 
    3331             :         /*
    3332             :          * Open partition indices (remember we do not support ON CONFLICT in
    3333             :          * case of partitioned tables, so we do not need support information
    3334             :          * for speculative insertion)
    3335             :          */
    3336         233 :         if (leaf_part_rri->ri_RelationDesc->rd_rel->relhasindex &&
    3337           1 :             leaf_part_rri->ri_IndexRelationDescs == NULL)
    3338           1 :             ExecOpenIndices(leaf_part_rri, false);
    3339             : 
    3340         232 :         leaf_part_rri++;
    3341         232 :         i++;
    3342             :     }
    3343          69 : }
    3344             : 
    3345             : /*
    3346             :  * ExecFindPartition -- Find a leaf partition in the partition tree rooted
    3347             :  * at parent, for the heap tuple contained in *slot
    3348             :  *
    3349             :  * estate must be non-NULL; we'll need it to compute any expressions in the
    3350             :  * partition key(s)
    3351             :  *
    3352             :  * If no leaf partition is found, this routine errors out with the appropriate
    3353             :  * error message, else it returns the leaf partition sequence number returned
    3354             :  * by get_partition_for_tuple() unchanged.
    3355             :  */
    3356             : int
    3357         178 : ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
    3358             :                   TupleTableSlot *slot, EState *estate)
    3359             : {
    3360             :     int         result;
    3361             :     PartitionDispatchData *failed_at;
    3362             :     TupleTableSlot *failed_slot;
    3363             : 
    3364             :     /*
    3365             :      * First check the root table's partition constraint, if any.  No point in
    3366             :      * routing the tuple if it doesn't belong in the root table itself.
    3367             :      */
    3368         178 :     if (resultRelInfo->ri_PartitionCheck)
    3369           4 :         ExecPartitionCheck(resultRelInfo, slot, estate);
    3370             : 
    3371         177 :     result = get_partition_for_tuple(pd, slot, estate,
    3372             :                                      &failed_at, &failed_slot);
    3373         177 :     if (result < 0)
    3374             :     {
    3375             :         Relation    failed_rel;
    3376             :         Datum       key_values[PARTITION_MAX_KEYS];
    3377             :         bool        key_isnull[PARTITION_MAX_KEYS];
    3378             :         char       *val_desc;
    3379          11 :         ExprContext *ecxt = GetPerTupleExprContext(estate);
    3380             : 
    3381          11 :         failed_rel = failed_at->reldesc;
    3382          11 :         ecxt->ecxt_scantuple = failed_slot;
    3383          11 :         FormPartitionKeyDatum(failed_at, failed_slot, estate,
    3384             :                               key_values, key_isnull);
    3385          11 :         val_desc = ExecBuildSlotPartitionKeyDescription(failed_rel,
    3386             :                                                         key_values,
    3387             :                                                         key_isnull,
    3388             :                                                         64);
    3389          11 :         Assert(OidIsValid(RelationGetRelid(failed_rel)));
    3390          11 :         ereport(ERROR,
    3391             :                 (errcode(ERRCODE_CHECK_VIOLATION),
    3392             :                  errmsg("no partition of relation \"%s\" found for row",
    3393             :                         RelationGetRelationName(failed_rel)),
    3394             :                  val_desc ? errdetail("Partition key of the failing row contains %s.", val_desc) : 0));
    3395             :     }
    3396             : 
    3397         166 :     return result;
    3398             : }
    3399             : 
    3400             : /*
    3401             :  * BuildSlotPartitionKeyDescription
    3402             :  *
    3403             :  * This works very much like BuildIndexValueDescription() and is currently
    3404             :  * used for building error messages when ExecFindPartition() fails to find
    3405             :  * partition for a row.
    3406             :  */
    3407             : static char *
    3408          11 : ExecBuildSlotPartitionKeyDescription(Relation rel,
    3409             :                                      Datum *values,
    3410             :                                      bool *isnull,
    3411             :                                      int maxfieldlen)
    3412             : {
    3413             :     StringInfoData buf;
    3414          11 :     PartitionKey key = RelationGetPartitionKey(rel);
    3415          11 :     int         partnatts = get_partition_natts(key);
    3416             :     int         i;
    3417          11 :     Oid         relid = RelationGetRelid(rel);
    3418             :     AclResult   aclresult;
    3419             : 
    3420          11 :     if (check_enable_rls(relid, InvalidOid, true) == RLS_ENABLED)
    3421           0 :         return NULL;
    3422             : 
    3423             :     /* If the user has table-level access, just go build the description. */
    3424          11 :     aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_SELECT);
    3425          11 :     if (aclresult != ACLCHECK_OK)
    3426             :     {
    3427             :         /*
    3428             :          * Step through the columns of the partition key and make sure the
    3429             :          * user has SELECT rights on all of them.
    3430             :          */
    3431           4 :         for (i = 0; i < partnatts; i++)
    3432             :         {
    3433           3 :             AttrNumber  attnum = get_partition_col_attnum(key, i);
    3434             : 
    3435             :             /*
    3436             :              * If this partition key column is an expression, we return no
    3437             :              * detail rather than try to figure out what column(s) the
    3438             :              * expression includes and if the user has SELECT rights on them.
    3439             :              */
    3440           5 :             if (attnum == InvalidAttrNumber ||
    3441           2 :                 pg_attribute_aclcheck(relid, attnum, GetUserId(),
    3442             :                                       ACL_SELECT) != ACLCHECK_OK)
    3443           2 :                 return NULL;
    3444             :         }
    3445             :     }
    3446             : 
    3447           9 :     initStringInfo(&buf);
    3448           9 :     appendStringInfo(&buf, "(%s) = (",
    3449             :                      pg_get_partkeydef_columns(relid, true));
    3450             : 
    3451          23 :     for (i = 0; i < partnatts; i++)
    3452             :     {
    3453             :         char       *val;
    3454             :         int         vallen;
    3455             : 
    3456          14 :         if (isnull[i])
    3457           2 :             val = "null";
    3458             :         else
    3459             :         {
    3460             :             Oid         foutoid;
    3461             :             bool        typisvarlena;
    3462             : 
    3463          12 :             getTypeOutputInfo(get_partition_col_typid(key, i),
    3464             :                               &foutoid, &typisvarlena);
    3465          12 :             val = OidOutputFunctionCall(foutoid, values[i]);
    3466             :         }
    3467             : 
    3468          14 :         if (i > 0)
    3469           5 :             appendStringInfoString(&buf, ", ");
    3470             : 
    3471             :         /* truncate if needed */
    3472          14 :         vallen = strlen(val);
    3473          14 :         if (vallen <= maxfieldlen)
    3474          14 :             appendStringInfoString(&buf, val);
    3475             :         else
    3476             :         {
    3477           0 :             vallen = pg_mbcliplen(val, vallen, maxfieldlen);
    3478           0 :             appendBinaryStringInfo(&buf, val, vallen);
    3479           0 :             appendStringInfoString(&buf, "...");
    3480             :         }
    3481             :     }
    3482             : 
    3483           9 :     appendStringInfoChar(&buf, ')');
    3484             : 
    3485           9 :     return buf.data;
    3486             : }

Generated by: LCOV version 1.11