PostgreSQL Source Code  git master
execMain.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/transam.h"
#include "access/xact.h"
#include "catalog/namespace.h"
#include "catalog/pg_publication.h"
#include "commands/matview.h"
#include "commands/trigger.h"
#include "executor/execdebug.h"
#include "foreign/fdwapi.h"
#include "jit/jit.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/partcache.h"
#include "utils/rls.h"
#include "utils/ruleutils.h"
#include "utils/snapmgr.h"
#include "utils/tqual.h"
Include dependency graph for execMain.c:

Go to the source code of this file.

Macros

#define GetInsertedColumns(relinfo, estate)   (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->insertedCols)
 
#define GetUpdatedColumns(relinfo, estate)   (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
 

Functions

static void InitPlan (QueryDesc *queryDesc, int eflags)
 
static void CheckValidRowMarkRel (Relation rel, RowMarkType markType)
 
static void ExecPostprocessPlan (EState *estate)
 
static void ExecEndPlan (PlanState *planstate, EState *estate)
 
static void ExecutePlan (EState *estate, PlanState *planstate, bool use_parallel_mode, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, DestReceiver *dest, bool execute_once)
 
static bool ExecCheckRTEPerms (RangeTblEntry *rte)
 
static bool ExecCheckRTEPermsModified (Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms)
 
static void ExecCheckXactReadOnly (PlannedStmt *plannedstmt)
 
static char * ExecBuildSlotValueDescription (Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
 
static void EvalPlanQualStart (EPQState *epqstate, EState *parentestate, Plan *planTree)
 
void ExecutorStart (QueryDesc *queryDesc, int eflags)
 
void standard_ExecutorStart (QueryDesc *queryDesc, int eflags)
 
void ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
 
void standard_ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
 
void ExecutorFinish (QueryDesc *queryDesc)
 
void standard_ExecutorFinish (QueryDesc *queryDesc)
 
void ExecutorEnd (QueryDesc *queryDesc)
 
void standard_ExecutorEnd (QueryDesc *queryDesc)
 
void ExecutorRewind (QueryDesc *queryDesc)
 
bool ExecCheckRTPerms (List *rangeTable, bool ereport_on_violation)
 
void CheckValidResultRel (ResultRelInfo *resultRelInfo, CmdType operation)
 
void InitResultRelInfo (ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
 
ResultRelInfoExecGetTriggerResultRel (EState *estate, Oid relid)
 
void ExecCleanUpTriggerState (EState *estate)
 
bool ExecContextForcesOids (PlanState *planstate, bool *hasoids)
 
static const char * ExecRelCheck (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
bool ExecPartitionCheck (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
 
void ExecPartitionCheckEmitError (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
void ExecConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
void ExecWithCheckOptions (WCOKind kind, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
LockTupleMode ExecUpdateLockMode (EState *estate, ResultRelInfo *relinfo)
 
ExecRowMarkExecFindRowMark (EState *estate, Index rti, bool missing_ok)
 
ExecAuxRowMarkExecBuildAuxRowMark (ExecRowMark *erm, List *targetlist)
 
TupleTableSlotEvalPlanQual (EState *estate, EPQState *epqstate, Relation relation, Index rti, int lockmode, ItemPointer tid, TransactionId priorXmax)
 
HeapTuple EvalPlanQualFetch (EState *estate, Relation relation, int lockmode, LockWaitPolicy wait_policy, ItemPointer tid, TransactionId priorXmax)
 
void EvalPlanQualInit (EPQState *epqstate, EState *estate, Plan *subplan, List *auxrowmarks, int epqParam)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
void EvalPlanQualSetTuple (EPQState *epqstate, Index rti, HeapTuple tuple)
 
HeapTuple EvalPlanQualGetTuple (EPQState *epqstate, Index rti)
 
void EvalPlanQualFetchRowMarks (EPQState *epqstate)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate, EState *parentestate)
 
void EvalPlanQualEnd (EPQState *epqstate)
 

Variables

ExecutorStart_hook_type ExecutorStart_hook = NULL
 
ExecutorRun_hook_type ExecutorRun_hook = NULL
 
ExecutorFinish_hook_type ExecutorFinish_hook = NULL
 
ExecutorEnd_hook_type ExecutorEnd_hook = NULL
 
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL
 

Macro Definition Documentation

◆ GetInsertedColumns

#define GetInsertedColumns (   relinfo,
  estate 
)    (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->insertedCols)

Definition at line 110 of file execMain.c.

Referenced by ExecConstraints(), ExecPartitionCheckEmitError(), and ExecWithCheckOptions().

◆ GetUpdatedColumns

#define GetUpdatedColumns (   relinfo,
  estate 
)    (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)

Function Documentation

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation 
)

Definition at line 1104 of file execMain.c.

References CheckCmdReplicaIdentity(), CMD_DELETE, CMD_INSERT, CMD_UPDATE, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FdwRoutine::ExecForeignDelete, FdwRoutine::ExecForeignInsert, FdwRoutine::ExecForeignUpdate, FdwRoutine::IsForeignRelUpdatable, MatViewIncrementalMaintenanceIsEnabled(), RelationData::rd_rel, RelationGetRelationName, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_RelationDesc, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, and RelationData::trigdesc.

Referenced by CopyFrom(), ExecInitModifyTable(), ExecInitPartitionInfo(), and ExecPrepareTupleRouting().

1105 {
1106  Relation resultRel = resultRelInfo->ri_RelationDesc;
1107  TriggerDesc *trigDesc = resultRel->trigdesc;
1108  FdwRoutine *fdwroutine;
1109 
1110  switch (resultRel->rd_rel->relkind)
1111  {
1112  case RELKIND_RELATION:
1113  case RELKIND_PARTITIONED_TABLE:
1114  CheckCmdReplicaIdentity(resultRel, operation);
1115  break;
1116  case RELKIND_SEQUENCE:
1117  ereport(ERROR,
1118  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1119  errmsg("cannot change sequence \"%s\"",
1120  RelationGetRelationName(resultRel))));
1121  break;
1122  case RELKIND_TOASTVALUE:
1123  ereport(ERROR,
1124  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1125  errmsg("cannot change TOAST relation \"%s\"",
1126  RelationGetRelationName(resultRel))));
1127  break;
1128  case RELKIND_VIEW:
1129 
1130  /*
1131  * Okay only if there's a suitable INSTEAD OF trigger. Messages
1132  * here should match rewriteHandler.c's rewriteTargetView, except
1133  * that we omit errdetail because we haven't got the information
1134  * handy (and given that we really shouldn't get here anyway, it's
1135  * not worth great exertion to get).
1136  */
1137  switch (operation)
1138  {
1139  case CMD_INSERT:
1140  if (!trigDesc || !trigDesc->trig_insert_instead_row)
1141  ereport(ERROR,
1142  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1143  errmsg("cannot insert into view \"%s\"",
1144  RelationGetRelationName(resultRel)),
1145  errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
1146  break;
1147  case CMD_UPDATE:
1148  if (!trigDesc || !trigDesc->trig_update_instead_row)
1149  ereport(ERROR,
1150  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1151  errmsg("cannot update view \"%s\"",
1152  RelationGetRelationName(resultRel)),
1153  errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
1154  break;
1155  case CMD_DELETE:
1156  if (!trigDesc || !trigDesc->trig_delete_instead_row)
1157  ereport(ERROR,
1158  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1159  errmsg("cannot delete from view \"%s\"",
1160  RelationGetRelationName(resultRel)),
1161  errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
1162  break;
1163  default:
1164  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1165  break;
1166  }
1167  break;
1168  case RELKIND_MATVIEW:
1170  ereport(ERROR,
1171  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1172  errmsg("cannot change materialized view \"%s\"",
1173  RelationGetRelationName(resultRel))));
1174  break;
1175  case RELKIND_FOREIGN_TABLE:
1176  /* Okay only if the FDW supports it */
1177  fdwroutine = resultRelInfo->ri_FdwRoutine;
1178  switch (operation)
1179  {
1180  case CMD_INSERT:
1181  if (fdwroutine->ExecForeignInsert == NULL)
1182  ereport(ERROR,
1183  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1184  errmsg("cannot insert into foreign table \"%s\"",
1185  RelationGetRelationName(resultRel))));
1186  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1187  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1188  ereport(ERROR,
1189  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1190  errmsg("foreign table \"%s\" does not allow inserts",
1191  RelationGetRelationName(resultRel))));
1192  break;
1193  case CMD_UPDATE:
1194  if (fdwroutine->ExecForeignUpdate == NULL)
1195  ereport(ERROR,
1196  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1197  errmsg("cannot update foreign table \"%s\"",
1198  RelationGetRelationName(resultRel))));
1199  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1200  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1201  ereport(ERROR,
1202  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1203  errmsg("foreign table \"%s\" does not allow updates",
1204  RelationGetRelationName(resultRel))));
1205  break;
1206  case CMD_DELETE:
1207  if (fdwroutine->ExecForeignDelete == NULL)
1208  ereport(ERROR,
1209  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1210  errmsg("cannot delete from foreign table \"%s\"",
1211  RelationGetRelationName(resultRel))));
1212  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1213  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1214  ereport(ERROR,
1215  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1216  errmsg("foreign table \"%s\" does not allow deletes",
1217  RelationGetRelationName(resultRel))));
1218  break;
1219  default:
1220  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1221  break;
1222  }
1223  break;
1224  default:
1225  ereport(ERROR,
1226  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1227  errmsg("cannot change relation \"%s\"",
1228  RelationGetRelationName(resultRel))));
1229  break;
1230  }
1231 }
ExecForeignDelete_function ExecForeignDelete
Definition: fdwapi.h:212
Relation ri_RelationDesc
Definition: execnodes.h:397
int errhint(const char *fmt,...)
Definition: elog.c:987
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition: matview.c:912
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:210
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:84
bool trig_insert_instead_row
Definition: reltrigger.h:57
#define ERROR
Definition: elog.h:43
TriggerDesc * trigdesc
Definition: rel.h:90
#define RelationGetRelationName(relation)
Definition: rel.h:441
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:421
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
#define ereport(elevel, rest)
Definition: elog.h:122
bool trig_update_instead_row
Definition: reltrigger.h:62
bool trig_delete_instead_row
Definition: reltrigger.h:67
ExecForeignUpdate_function ExecForeignUpdate
Definition: fdwapi.h:211
int errmsg(const char *fmt,...)
Definition: elog.c:797
IsForeignRelUpdatable_function IsForeignRelUpdatable
Definition: fdwapi.h:216
#define elog
Definition: elog.h:219

◆ CheckValidRowMarkRel()

static void CheckValidRowMarkRel ( Relation  rel,
RowMarkType  markType 
)
static

Definition at line 1240 of file execMain.c.

References ereport, errcode(), errmsg(), ERROR, GetFdwRoutineForRelation(), RelationData::rd_rel, FdwRoutine::RefetchForeignRow, RelationGetRelationName, and ROW_MARK_REFERENCE.

Referenced by InitPlan().

1241 {
1242  FdwRoutine *fdwroutine;
1243 
1244  switch (rel->rd_rel->relkind)
1245  {
1246  case RELKIND_RELATION:
1247  case RELKIND_PARTITIONED_TABLE:
1248  /* OK */
1249  break;
1250  case RELKIND_SEQUENCE:
1251  /* Must disallow this because we don't vacuum sequences */
1252  ereport(ERROR,
1253  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1254  errmsg("cannot lock rows in sequence \"%s\"",
1255  RelationGetRelationName(rel))));
1256  break;
1257  case RELKIND_TOASTVALUE:
1258  /* We could allow this, but there seems no good reason to */
1259  ereport(ERROR,
1260  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1261  errmsg("cannot lock rows in TOAST relation \"%s\"",
1262  RelationGetRelationName(rel))));
1263  break;
1264  case RELKIND_VIEW:
1265  /* Should not get here; planner should have expanded the view */
1266  ereport(ERROR,
1267  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1268  errmsg("cannot lock rows in view \"%s\"",
1269  RelationGetRelationName(rel))));
1270  break;
1271  case RELKIND_MATVIEW:
1272  /* Allow referencing a matview, but not actual locking clauses */
1273  if (markType != ROW_MARK_REFERENCE)
1274  ereport(ERROR,
1275  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1276  errmsg("cannot lock rows in materialized view \"%s\"",
1277  RelationGetRelationName(rel))));
1278  break;
1279  case RELKIND_FOREIGN_TABLE:
1280  /* Okay only if the FDW supports it */
1281  fdwroutine = GetFdwRoutineForRelation(rel, false);
1282  if (fdwroutine->RefetchForeignRow == NULL)
1283  ereport(ERROR,
1284  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1285  errmsg("cannot lock rows in foreign table \"%s\"",
1286  RelationGetRelationName(rel))));
1287  break;
1288  default:
1289  ereport(ERROR,
1290  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1291  errmsg("cannot lock rows in relation \"%s\"",
1292  RelationGetRelationName(rel))));
1293  break;
1294  }
1295 }
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:84
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:224

◆ EvalPlanQual()

TupleTableSlot* EvalPlanQual ( EState estate,
EPQState epqstate,
Relation  relation,
Index  rti,
int  lockmode,
ItemPointer  tid,
TransactionId  priorXmax 
)

Definition at line 2504 of file execMain.c.

References Assert, EvalPlanQualBegin(), EvalPlanQualFetch(), EvalPlanQualFetchRowMarks(), EvalPlanQualNext(), EvalPlanQualSetTuple(), ExecMaterializeSlot(), LockWaitBlock, HeapTupleData::t_self, and TupIsNull.

Referenced by ExecDelete(), ExecUpdate(), and GetTupleForTrigger().

2507 {
2508  TupleTableSlot *slot;
2509  HeapTuple copyTuple;
2510 
2511  Assert(rti > 0);
2512 
2513  /*
2514  * Get and lock the updated version of the row; if fail, return NULL.
2515  */
2516  copyTuple = EvalPlanQualFetch(estate, relation, lockmode, LockWaitBlock,
2517  tid, priorXmax);
2518 
2519  if (copyTuple == NULL)
2520  return NULL;
2521 
2522  /*
2523  * For UPDATE/DELETE we have to return tid of actual row we're executing
2524  * PQ for.
2525  */
2526  *tid = copyTuple->t_self;
2527 
2528  /*
2529  * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2530  */
2531  EvalPlanQualBegin(epqstate, estate);
2532 
2533  /*
2534  * Free old test tuple, if any, and store new tuple where relation's scan
2535  * node will see it
2536  */
2537  EvalPlanQualSetTuple(epqstate, rti, copyTuple);
2538 
2539  /*
2540  * Fetch any non-locked source rows
2541  */
2542  EvalPlanQualFetchRowMarks(epqstate);
2543 
2544  /*
2545  * Run the EPQ query. We assume it will return at most one tuple.
2546  */
2547  slot = EvalPlanQualNext(epqstate);
2548 
2549  /*
2550  * If we got a tuple, force the slot to materialize the tuple so that it
2551  * is not dependent on any local state in the EPQ query (in particular,
2552  * it's highly likely that the slot contains references to any pass-by-ref
2553  * datums that may be present in copyTuple). As with the next step, this
2554  * is to guard against early re-use of the EPQ query.
2555  */
2556  if (!TupIsNull(slot))
2557  (void) ExecMaterializeSlot(slot);
2558 
2559  /*
2560  * Clear out the test tuple. This is needed in case the EPQ query is
2561  * re-used to test a tuple for a different relation. (Not clear that can
2562  * really happen, but let's be safe.)
2563  */
2564  EvalPlanQualSetTuple(epqstate, rti, NULL);
2565 
2566  return slot;
2567 }
void EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
Definition: execMain.c:2868
HeapTuple EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, LockWaitPolicy wait_policy, ItemPointer tid, TransactionId priorXmax)
Definition: execMain.c:2591
void EvalPlanQualFetchRowMarks(EPQState *epqstate)
Definition: execMain.c:2903
void EvalPlanQualBegin(EPQState *epqstate, EState *parentestate)
Definition: execMain.c:3063
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition: execMain.c:3047
ItemPointerData t_self
Definition: htup.h:65
#define TupIsNull(slot)
Definition: tuptable.h:146
#define Assert(condition)
Definition: c.h:699
HeapTuple ExecMaterializeSlot(TupleTableSlot *slot)
Definition: execTuples.c:781

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate,
EState parentestate 
)

Definition at line 3063 of file execMain.c.

References bms_add_member(), PlanState::chgParam, EPQState::epqParam, EState::es_epqScanDone, EState::es_param_exec_vals, EState::es_plannedstmt, EState::es_range_table, EPQState::estate, EvalPlanQualStart(), i, ParamExecData::isnull, list_length(), MemSet, NIL, PlannedStmt::paramExecTypes, EPQState::plan, EPQState::planstate, and ParamExecData::value.

Referenced by EvalPlanQual(), and ExecLockRows().

3064 {
3065  EState *estate = epqstate->estate;
3066 
3067  if (estate == NULL)
3068  {
3069  /* First time through, so create a child EState */
3070  EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
3071  }
3072  else
3073  {
3074  /*
3075  * We already have a suitable child EPQ tree, so just reset it.
3076  */
3077  int rtsize = list_length(parentestate->es_range_table);
3078  PlanState *planstate = epqstate->planstate;
3079 
3080  MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
3081 
3082  /* Recopy current values of parent parameters */
3083  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
3084  {
3085  int i;
3086 
3087  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
3088 
3089  while (--i >= 0)
3090  {
3091  /* copy value if any, but not execPlan link */
3092  estate->es_param_exec_vals[i].value =
3093  parentestate->es_param_exec_vals[i].value;
3094  estate->es_param_exec_vals[i].isnull =
3095  parentestate->es_param_exec_vals[i].isnull;
3096  }
3097  }
3098 
3099  /*
3100  * Mark child plan tree as needing rescan at all scan nodes. The
3101  * first ExecProcNode will take care of actually doing the rescan.
3102  */
3103  planstate->chgParam = bms_add_member(planstate->chgParam,
3104  epqstate->epqParam);
3105  }
3106 }
List * paramExecTypes
Definition: plannodes.h:95
#define NIL
Definition: pg_list.h:69
PlannedStmt * es_plannedstmt
Definition: execnodes.h:481
#define MemSet(start, val, len)
Definition: c.h:908
List * es_range_table
Definition: execnodes.h:480
PlanState * planstate
Definition: execnodes.h:993
ParamExecData * es_param_exec_vals
Definition: execnodes.h:518
bool isnull
Definition: params.h:149
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
Definition: execMain.c:3115
Bitmapset * chgParam
Definition: execnodes.h:941
Plan * plan
Definition: execnodes.h:995
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
int i
bool * es_epqScanDone
Definition: execnodes.h:560
Datum value
Definition: params.h:148
int epqParam
Definition: execnodes.h:997
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 3256 of file execMain.c.

References EState::es_query_cxt, EState::es_subplanstates, EState::es_tupleTable, EPQState::estate, ExecCleanUpTriggerState(), ExecEndNode(), ExecResetTupleTable(), FreeExecutorState(), lfirst, MemoryContextSwitchTo(), EPQState::origslot, and EPQState::planstate.

Referenced by apply_handle_delete(), apply_handle_update(), EvalPlanQualSetPlan(), ExecEndLockRows(), and ExecEndModifyTable().

3257 {
3258  EState *estate = epqstate->estate;
3259  MemoryContext oldcontext;
3260  ListCell *l;
3261 
3262  if (estate == NULL)
3263  return; /* idle, so nothing to do */
3264 
3265  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3266 
3267  ExecEndNode(epqstate->planstate);
3268 
3269  foreach(l, estate->es_subplanstates)
3270  {
3271  PlanState *subplanstate = (PlanState *) lfirst(l);
3272 
3273  ExecEndNode(subplanstate);
3274  }
3275 
3276  /* throw away the per-estate tuple table */
3277  ExecResetTupleTable(estate->es_tupleTable, false);
3278 
3279  /* close any trigger target relations attached to this EState */
3280  ExecCleanUpTriggerState(estate);
3281 
3282  MemoryContextSwitchTo(oldcontext);
3283 
3284  FreeExecutorState(estate);
3285 
3286  /* Mark EPQState idle */
3287  epqstate->estate = NULL;
3288  epqstate->planstate = NULL;
3289  epqstate->origslot = NULL;
3290 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:538
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:993
void FreeExecutorState(EState *estate)
Definition: execUtils.c:188
MemoryContext es_query_cxt
Definition: execnodes.h:523
TupleTableSlot * origslot
Definition: execnodes.h:994
List * es_tupleTable
Definition: execnodes.h:525
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:186
#define lfirst(lc)
Definition: pg_list.h:106
List * es_subplanstates
Definition: execnodes.h:538
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1474
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualFetch()

HeapTuple EvalPlanQualFetch ( EState estate,
Relation  relation,
int  lockmode,
LockWaitPolicy  wait_policy,
ItemPointer  tid,
TransactionId  priorXmax 
)

Definition at line 2591 of file execMain.c.

References Assert, buffer, ConditionalXactLockTableWait(), HeapUpdateFailureData::ctid, elog, ereport, errcode(), errmsg(), ERROR, EState::es_output_cid, heap_copytuple(), heap_fetch(), heap_lock_tuple(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleHeaderIndicatesMovedPartitions, HeapTupleHeaderIsSpeculative, HeapTupleInvisible, HeapTupleMayBeUpdated, HeapTupleSelfUpdated, HeapTupleUpdated, HeapTupleWouldBlock, InitDirtySnapshot, IsolationUsesXactSnapshot, ItemPointerEquals(), ItemPointerIndicatesMovedPartitions, LockWaitBlock, LockWaitError, LockWaitSkip, RelationGetRelationName, ReleaseBuffer(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, test(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, XactLockTableWait(), XLTW_FetchUpdated, SnapshotData::xmax, HeapUpdateFailureData::xmax, and SnapshotData::xmin.

Referenced by EvalPlanQual(), and ExecLockRows().

2594 {
2595  HeapTuple copyTuple = NULL;
2596  HeapTupleData tuple;
2597  SnapshotData SnapshotDirty;
2598 
2599  /*
2600  * fetch target tuple
2601  *
2602  * Loop here to deal with updated or busy tuples
2603  */
2604  InitDirtySnapshot(SnapshotDirty);
2605  tuple.t_self = *tid;
2606  for (;;)
2607  {
2608  Buffer buffer;
2609 
2610  if (heap_fetch(relation, &SnapshotDirty, &tuple, &buffer, true, NULL))
2611  {
2612  HTSU_Result test;
2613  HeapUpdateFailureData hufd;
2614 
2615  /*
2616  * If xmin isn't what we're expecting, the slot must have been
2617  * recycled and reused for an unrelated tuple. This implies that
2618  * the latest version of the row was deleted, so we need do
2619  * nothing. (Should be safe to examine xmin without getting
2620  * buffer's content lock. We assume reading a TransactionId to be
2621  * atomic, and Xmin never changes in an existing tuple, except to
2622  * invalid or frozen, and neither of those can match priorXmax.)
2623  */
2625  priorXmax))
2626  {
2627  ReleaseBuffer(buffer);
2628  return NULL;
2629  }
2630 
2631  /* otherwise xmin should not be dirty... */
2632  if (TransactionIdIsValid(SnapshotDirty.xmin))
2633  elog(ERROR, "t_xmin is uncommitted in tuple to be updated");
2634 
2635  /*
2636  * If tuple is being updated by other transaction then we have to
2637  * wait for its commit/abort, or die trying.
2638  */
2639  if (TransactionIdIsValid(SnapshotDirty.xmax))
2640  {
2641  ReleaseBuffer(buffer);
2642  switch (wait_policy)
2643  {
2644  case LockWaitBlock:
2645  XactLockTableWait(SnapshotDirty.xmax,
2646  relation, &tuple.t_self,
2648  break;
2649  case LockWaitSkip:
2650  if (!ConditionalXactLockTableWait(SnapshotDirty.xmax))
2651  return NULL; /* skip instead of waiting */
2652  break;
2653  case LockWaitError:
2654  if (!ConditionalXactLockTableWait(SnapshotDirty.xmax))
2655  ereport(ERROR,
2656  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
2657  errmsg("could not obtain lock on row in relation \"%s\"",
2658  RelationGetRelationName(relation))));
2659  break;
2660  }
2661  continue; /* loop back to repeat heap_fetch */
2662  }
2663 
2664  /*
2665  * If tuple was inserted by our own transaction, we have to check
2666  * cmin against es_output_cid: cmin >= current CID means our
2667  * command cannot see the tuple, so we should ignore it. Otherwise
2668  * heap_lock_tuple() will throw an error, and so would any later
2669  * attempt to update or delete the tuple. (We need not check cmax
2670  * because HeapTupleSatisfiesDirty will consider a tuple deleted
2671  * by our transaction dead, regardless of cmax.) We just checked
2672  * that priorXmax == xmin, so we can test that variable instead of
2673  * doing HeapTupleHeaderGetXmin again.
2674  */
2675  if (TransactionIdIsCurrentTransactionId(priorXmax) &&
2676  HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid)
2677  {
2678  ReleaseBuffer(buffer);
2679  return NULL;
2680  }
2681 
2682  /*
2683  * This is a live tuple, so now try to lock it.
2684  */
2685  test = heap_lock_tuple(relation, &tuple,
2686  estate->es_output_cid,
2687  lockmode, wait_policy,
2688  false, &buffer, &hufd);
2689  /* We now have two pins on the buffer, get rid of one */
2690  ReleaseBuffer(buffer);
2691 
2692  switch (test)
2693  {
2694  case HeapTupleSelfUpdated:
2695 
2696  /*
2697  * The target tuple was already updated or deleted by the
2698  * current command, or by a later command in the current
2699  * transaction. We *must* ignore the tuple in the former
2700  * case, so as to avoid the "Halloween problem" of
2701  * repeated update attempts. In the latter case it might
2702  * be sensible to fetch the updated tuple instead, but
2703  * doing so would require changing heap_update and
2704  * heap_delete to not complain about updating "invisible"
2705  * tuples, which seems pretty scary (heap_lock_tuple will
2706  * not complain, but few callers expect
2707  * HeapTupleInvisible, and we're not one of them). So for
2708  * now, treat the tuple as deleted and do not process.
2709  */
2710  ReleaseBuffer(buffer);
2711  return NULL;
2712 
2713  case HeapTupleMayBeUpdated:
2714  /* successfully locked */
2715  break;
2716 
2717  case HeapTupleUpdated:
2718  ReleaseBuffer(buffer);
2720  ereport(ERROR,
2721  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2722  errmsg("could not serialize access due to concurrent update")));
2724  ereport(ERROR,
2725  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2726  errmsg("tuple to be locked was already moved to another partition due to concurrent update")));
2727 
2728  /* Should not encounter speculative tuple on recheck */
2730  if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
2731  {
2732  /* it was updated, so look at the updated version */
2733  tuple.t_self = hufd.ctid;
2734  /* updated row should have xmin matching this xmax */
2735  priorXmax = hufd.xmax;
2736  continue;
2737  }
2738  /* tuple was deleted, so give up */
2739  return NULL;
2740 
2741  case HeapTupleWouldBlock:
2742  ReleaseBuffer(buffer);
2743  return NULL;
2744 
2745  case HeapTupleInvisible:
2746  elog(ERROR, "attempted to lock invisible tuple");
2747  break;
2748 
2749  default:
2750  ReleaseBuffer(buffer);
2751  elog(ERROR, "unrecognized heap_lock_tuple status: %u",
2752  test);
2753  return NULL; /* keep compiler quiet */
2754  }
2755 
2756  /*
2757  * We got tuple - now copy it for use by recheck query.
2758  */
2759  copyTuple = heap_copytuple(&tuple);
2760  ReleaseBuffer(buffer);
2761  break;
2762  }
2763 
2764  /*
2765  * If the referenced slot was actually empty, the latest version of
2766  * the row must have been deleted, so we need do nothing.
2767  */
2768  if (tuple.t_data == NULL)
2769  {
2770  ReleaseBuffer(buffer);
2771  return NULL;
2772  }
2773 
2774  /*
2775  * As above, if xmin isn't what we're expecting, do nothing.
2776  */
2778  priorXmax))
2779  {
2780  ReleaseBuffer(buffer);
2781  return NULL;
2782  }
2783 
2784  /*
2785  * If we get here, the tuple was found but failed SnapshotDirty.
2786  * Assuming the xmin is either a committed xact or our own xact (as it
2787  * certainly should be if we're trying to modify the tuple), this must
2788  * mean that the row was updated or deleted by either a committed xact
2789  * or our own xact. If it was deleted, we can ignore it; if it was
2790  * updated then chain up to the next version and repeat the whole
2791  * process.
2792  *
2793  * As above, it should be safe to examine xmax and t_ctid without the
2794  * buffer content lock, because they can't be changing.
2795  */
2796 
2797  /* check whether next version would be in a different partition */
2799  ereport(ERROR,
2800  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2801  errmsg("tuple to be locked was already moved to another partition due to concurrent update")));
2802 
2803  /* check whether tuple has been deleted */
2804  if (ItemPointerEquals(&tuple.t_self, &tuple.t_data->t_ctid))
2805  {
2806  /* deleted, so forget about it */
2807  ReleaseBuffer(buffer);
2808  return NULL;
2809  }
2810 
2811  /* updated, so look at the updated row */
2812  tuple.t_self = tuple.t_data->t_ctid;
2813  /* updated row should have xmin matching this xmax */
2814  priorXmax = HeapTupleHeaderGetUpdateXid(tuple.t_data);
2815  ReleaseBuffer(buffer);
2816  /* loop back to fetch next in chain */
2817  }
2818 
2819  /*
2820  * Return the copied tuple
2821  */
2822  return copyTuple;
2823 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:722
CommandId es_output_cid
Definition: execnodes.h:487
static void test(void)
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:765
HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tuple, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, bool follow_updates, Buffer *buffer, HeapUpdateFailureData *hufd)
Definition: heapam.c:4688
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:105
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1903
#define IsolationUsesXactSnapshot()
Definition: xact.h:50
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:428
int errcode(int sqlerrcode)
Definition: elog.c:575
#define HeapTupleHeaderIndicatesMovedPartitions(tup)
Definition: htup_details.h:444
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
bool ConditionalXactLockTableWait(TransactionId xid)
Definition: lmgr.c:627
HeapTupleHeader t_data
Definition: htup.h:68
#define ERROR
Definition: elog.h:43
#define InitDirtySnapshot(snapshotdata)
Definition: tqual.h:103
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
HTSU_Result
Definition: snapshot.h:121
#define RelationGetRelationName(relation)
Definition: rel.h:441
TransactionId xmax
Definition: snapshot.h:69
TransactionId xmin
Definition: snapshot.h:68
#define ereport(elevel, rest)
Definition: elog.h:122
TransactionId xmax
Definition: heapam.h:71
#define ItemPointerIndicatesMovedPartitions(pointer)
Definition: itemptr.h:184
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:554
#define Assert(condition)
Definition: c.h:699
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
int errmsg(const char *fmt,...)
Definition: elog.c:797
ItemPointerData ctid
Definition: heapam.h:70
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int Buffer
Definition: buf.h:23

◆ EvalPlanQualFetchRowMarks()

void EvalPlanQualFetchRowMarks ( EPQState epqstate)

Definition at line 2903 of file execMain.c.

References EPQState::arowMarks, Assert, buffer, ExecAuxRowMark::ctidAttNo, DatumGetHeapTupleHeader, DatumGetObjectId, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, EPQState::estate, EvalPlanQualSetTuple(), ExecGetJunkAttribute(), GetFdwRoutineForRelation(), heap_copytuple(), heap_expand_tuple(), heap_fetch(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetNatts, lfirst, ExecRowMark::markType, OidIsValid, EPQState::origslot, ExecRowMark::prti, RelationData::rd_rel, FdwRoutine::RefetchForeignRow, ExecRowMark::relation, RelationGetDescr, RelationGetRelationName, ReleaseBuffer(), ExecRowMark::relid, ROW_MARK_COPY, ROW_MARK_REFERENCE, ExecAuxRowMark::rowmark, RowMarkRequiresRowShareLock, ExecRowMark::rti, SnapshotAny, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, ExecAuxRowMark::toidAttNo, and ExecAuxRowMark::wholeAttNo.

Referenced by EvalPlanQual(), and ExecLockRows().

2904 {
2905  ListCell *l;
2906 
2907  Assert(epqstate->origslot != NULL);
2908 
2909  foreach(l, epqstate->arowMarks)
2910  {
2911  ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
2912  ExecRowMark *erm = aerm->rowmark;
2913  Datum datum;
2914  bool isNull;
2915  HeapTupleData tuple;
2916 
2918  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2919 
2920  /* clear any leftover test tuple for this rel */
2921  EvalPlanQualSetTuple(epqstate, erm->rti, NULL);
2922 
2923  /* if child rel, must check whether it produced this row */
2924  if (erm->rti != erm->prti)
2925  {
2926  Oid tableoid;
2927 
2928  datum = ExecGetJunkAttribute(epqstate->origslot,
2929  aerm->toidAttNo,
2930  &isNull);
2931  /* non-locked rels could be on the inside of outer joins */
2932  if (isNull)
2933  continue;
2934  tableoid = DatumGetObjectId(datum);
2935 
2936  Assert(OidIsValid(erm->relid));
2937  if (tableoid != erm->relid)
2938  {
2939  /* this child is inactive right now */
2940  continue;
2941  }
2942  }
2943 
2944  if (erm->markType == ROW_MARK_REFERENCE)
2945  {
2946  HeapTuple copyTuple;
2947 
2948  Assert(erm->relation != NULL);
2949 
2950  /* fetch the tuple's ctid */
2951  datum = ExecGetJunkAttribute(epqstate->origslot,
2952  aerm->ctidAttNo,
2953  &isNull);
2954  /* non-locked rels could be on the inside of outer joins */
2955  if (isNull)
2956  continue;
2957 
2958  /* fetch requests on foreign tables must be passed to their FDW */
2959  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2960  {
2961  FdwRoutine *fdwroutine;
2962  bool updated = false;
2963 
2964  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2965  /* this should have been checked already, but let's be safe */
2966  if (fdwroutine->RefetchForeignRow == NULL)
2967  ereport(ERROR,
2968  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2969  errmsg("cannot lock rows in foreign table \"%s\"",
2971  copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate,
2972  erm,
2973  datum,
2974  &updated);
2975  if (copyTuple == NULL)
2976  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2977 
2978  /*
2979  * Ideally we'd insist on updated == false here, but that
2980  * assumes that FDWs can track that exactly, which they might
2981  * not be able to. So just ignore the flag.
2982  */
2983  }
2984  else
2985  {
2986  /* ordinary table, fetch the tuple */
2987  Buffer buffer;
2988 
2989  tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
2990  if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
2991  false, NULL))
2992  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2993 
2994  if (HeapTupleHeaderGetNatts(tuple.t_data) <
2995  RelationGetDescr(erm->relation)->natts)
2996  {
2997  copyTuple = heap_expand_tuple(&tuple,
2998  RelationGetDescr(erm->relation));
2999  }
3000  else
3001  {
3002  /* successful, copy tuple */
3003  copyTuple = heap_copytuple(&tuple);
3004  }
3005  ReleaseBuffer(buffer);
3006  }
3007 
3008  /* store tuple */
3009  EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
3010  }
3011  else
3012  {
3013  HeapTupleHeader td;
3014 
3015  Assert(erm->markType == ROW_MARK_COPY);
3016 
3017  /* fetch the whole-row Var for the relation */
3018  datum = ExecGetJunkAttribute(epqstate->origslot,
3019  aerm->wholeAttNo,
3020  &isNull);
3021  /* non-locked rels could be on the inside of outer joins */
3022  if (isNull)
3023  continue;
3024  td = DatumGetHeapTupleHeader(datum);
3025 
3026  /* build a temporary HeapTuple control structure */
3028  tuple.t_data = td;
3029  /* relation might be a foreign table, if so provide tableoid */
3030  tuple.t_tableOid = erm->relid;
3031  /* also copy t_ctid in case there's valid data there */
3032  tuple.t_self = td->t_ctid;
3033 
3034  /* copy and store tuple */
3035  EvalPlanQualSetTuple(epqstate, erm->rti,
3036  heap_copytuple(&tuple));
3037  }
3038  }
3039 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:722
#define RelationGetDescr(relation)
Definition: rel.h:433
void EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
Definition: execMain.c:2868
Relation relation
Definition: execnodes.h:596
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1903
#define DatumGetObjectId(X)
Definition: postgres.h:485
int errcode(int sqlerrcode)
Definition: elog.c:575
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:264
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:994
ItemPointerData * ItemPointer
Definition: itemptr.h:49
ExecRowMark * rowmark
Definition: execnodes.h:623
HeapTupleHeader t_data
Definition: htup.h:68
#define ERROR
Definition: elog.h:43
#define HeapTupleHeaderGetNatts(tup)
Definition: htup_details.h:544
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
List * arowMarks
Definition: execnodes.h:996
uint32 t_len
Definition: htup.h:64
Index rti
Definition: execnodes.h:598
AttrNumber wholeAttNo
Definition: execnodes.h:626
Index prti
Definition: execnodes.h:599
HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition: heaptuple.c:1023
#define RelationGetRelationName(relation)
Definition: rel.h:441
Oid t_tableOid
Definition: htup.h:66
TupleTableSlot * origslot
Definition: execnodes.h:994
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:367
#define SnapshotAny
Definition: tqual.h:28
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
RowMarkType markType
Definition: execnodes.h:601
AttrNumber toidAttNo
Definition: execnodes.h:625
#define DatumGetPointer(X)
Definition: postgres.h:534
int errmsg(const char *fmt,...)
Definition: elog.c:797
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: execJunk.c:248
#define elog
Definition: elog.h:219
EState * estate
Definition: execnodes.h:992
int Buffer
Definition: buf.h:23
AttrNumber ctidAttNo
Definition: execnodes.h:624
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:224
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451

◆ EvalPlanQualGetTuple()

HeapTuple EvalPlanQualGetTuple ( EPQState epqstate,
Index  rti 
)

Definition at line 2888 of file execMain.c.

References Assert, EState::es_epqTuple, and EPQState::estate.

2889 {
2890  EState *estate = epqstate->estate;
2891 
2892  Assert(rti > 0);
2893 
2894  return estate->es_epqTuple[rti - 1];
2895 }
HeapTuple * es_epqTuple
Definition: execnodes.h:558
#define Assert(condition)
Definition: c.h:699
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualInit()

void EvalPlanQualInit ( EPQState epqstate,
EState estate,
Plan subplan,
List auxrowmarks,
int  epqParam 
)

Definition at line 2833 of file execMain.c.

References EPQState::arowMarks, EPQState::epqParam, EPQState::estate, EPQState::origslot, EPQState::plan, and EPQState::planstate.

Referenced by apply_handle_delete(), apply_handle_update(), ExecInitLockRows(), and ExecInitModifyTable().

2835 {
2836  /* Mark the EPQ state inactive */
2837  epqstate->estate = NULL;
2838  epqstate->planstate = NULL;
2839  epqstate->origslot = NULL;
2840  /* ... and remember data that EvalPlanQualBegin will need */
2841  epqstate->plan = subplan;
2842  epqstate->arowMarks = auxrowmarks;
2843  epqstate->epqParam = epqParam;
2844 }
PlanState * planstate
Definition: execnodes.h:993
List * arowMarks
Definition: execnodes.h:996
TupleTableSlot * origslot
Definition: execnodes.h:994
Plan * plan
Definition: execnodes.h:995
int epqParam
Definition: execnodes.h:997
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 3047 of file execMain.c.

References EState::es_query_cxt, EPQState::estate, ExecProcNode(), MemoryContextSwitchTo(), and EPQState::planstate.

Referenced by EvalPlanQual(), and ExecLockRows().

3048 {
3049  MemoryContext oldcontext;
3050  TupleTableSlot *slot;
3051 
3052  oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
3053  slot = ExecProcNode(epqstate->planstate);
3054  MemoryContextSwitchTo(oldcontext);
3055 
3056  return slot;
3057 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:993
MemoryContext es_query_cxt
Definition: execnodes.h:523
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:232
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualSetPlan()

void EvalPlanQualSetPlan ( EPQState epqstate,
Plan subplan,
List auxrowmarks 
)

Definition at line 2852 of file execMain.c.

References EPQState::arowMarks, EvalPlanQualEnd(), and EPQState::plan.

Referenced by ExecInitModifyTable(), and ExecModifyTable().

2853 {
2854  /* If we have a live EPQ query, shut it down */
2855  EvalPlanQualEnd(epqstate);
2856  /* And set/change the plan pointer */
2857  epqstate->plan = subplan;
2858  /* The rowmarks depend on the plan, too */
2859  epqstate->arowMarks = auxrowmarks;
2860 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3256
List * arowMarks
Definition: execnodes.h:996
Plan * plan
Definition: execnodes.h:995

◆ EvalPlanQualSetTuple()

void EvalPlanQualSetTuple ( EPQState epqstate,
Index  rti,
HeapTuple  tuple 
)

Definition at line 2868 of file execMain.c.

References Assert, EState::es_epqTuple, EState::es_epqTupleSet, EPQState::estate, and heap_freetuple().

Referenced by EvalPlanQual(), EvalPlanQualFetchRowMarks(), and ExecLockRows().

2869 {
2870  EState *estate = epqstate->estate;
2871 
2872  Assert(rti > 0);
2873 
2874  /*
2875  * free old test tuple, if any, and store new tuple where relation's scan
2876  * node will see it
2877  */
2878  if (estate->es_epqTuple[rti - 1] != NULL)
2879  heap_freetuple(estate->es_epqTuple[rti - 1]);
2880  estate->es_epqTuple[rti - 1] = tuple;
2881  estate->es_epqTupleSet[rti - 1] = true;
2882 }
HeapTuple * es_epqTuple
Definition: execnodes.h:558
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
#define Assert(condition)
Definition: c.h:699
bool * es_epqTupleSet
Definition: execnodes.h:559
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualStart()

static void EvalPlanQualStart ( EPQState epqstate,
EState parentestate,
Plan planTree 
)
static

Definition at line 3115 of file execMain.c.

References Assert, CreateExecutorState(), EState::es_crosscheck_snapshot, EState::es_direction, EState::es_epqScanDone, EState::es_epqTuple, EState::es_epqTupleSet, EState::es_instrument, EState::es_junkFilter, EState::es_num_result_relations, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_plannedstmt, EState::es_query_cxt, EState::es_range_table, EState::es_result_relations, EState::es_rowMarks, EState::es_snapshot, EState::es_subplanstates, EState::es_top_eflags, EState::es_tupleTable, EPQState::estate, ExecInitNode(), ForwardScanDirection, i, ParamExecData::isnull, lappend(), lfirst, list_length(), MemoryContextSwitchTo(), NIL, palloc(), palloc0(), PlannedStmt::paramExecTypes, EPQState::planstate, PlannedStmt::subplans, and ParamExecData::value.

Referenced by EvalPlanQualBegin().

3116 {
3117  EState *estate;
3118  int rtsize;
3119  MemoryContext oldcontext;
3120  ListCell *l;
3121 
3122  rtsize = list_length(parentestate->es_range_table);
3123 
3124  epqstate->estate = estate = CreateExecutorState();
3125 
3126  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3127 
3128  /*
3129  * Child EPQ EStates share the parent's copy of unchanging state such as
3130  * the snapshot, rangetable, result-rel info, and external Param info.
3131  * They need their own copies of local state, including a tuple table,
3132  * es_param_exec_vals, etc.
3133  *
3134  * The ResultRelInfo array management is trickier than it looks. We
3135  * create a fresh array for the child but copy all the content from the
3136  * parent. This is because it's okay for the child to share any
3137  * per-relation state the parent has already created --- but if the child
3138  * sets up any ResultRelInfo fields, such as its own junkfilter, that
3139  * state must *not* propagate back to the parent. (For one thing, the
3140  * pointed-to data is in a memory context that won't last long enough.)
3141  */
3143  estate->es_snapshot = parentestate->es_snapshot;
3144  estate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
3145  estate->es_range_table = parentestate->es_range_table;
3146  estate->es_plannedstmt = parentestate->es_plannedstmt;
3147  estate->es_junkFilter = parentestate->es_junkFilter;
3148  estate->es_output_cid = parentestate->es_output_cid;
3149  if (parentestate->es_num_result_relations > 0)
3150  {
3151  int numResultRelations = parentestate->es_num_result_relations;
3152  ResultRelInfo *resultRelInfos;
3153 
3154  resultRelInfos = (ResultRelInfo *)
3155  palloc(numResultRelations * sizeof(ResultRelInfo));
3156  memcpy(resultRelInfos, parentestate->es_result_relations,
3157  numResultRelations * sizeof(ResultRelInfo));
3158  estate->es_result_relations = resultRelInfos;
3159  estate->es_num_result_relations = numResultRelations;
3160  }
3161  /* es_result_relation_info must NOT be copied */
3162  /* es_trig_target_relations must NOT be copied */
3163  estate->es_rowMarks = parentestate->es_rowMarks;
3164  estate->es_top_eflags = parentestate->es_top_eflags;
3165  estate->es_instrument = parentestate->es_instrument;
3166  /* es_auxmodifytables must NOT be copied */
3167 
3168  /*
3169  * The external param list is simply shared from parent. The internal
3170  * param workspace has to be local state, but we copy the initial values
3171  * from the parent, so as to have access to any param values that were
3172  * already set from other parts of the parent's plan tree.
3173  */
3174  estate->es_param_list_info = parentestate->es_param_list_info;
3175  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
3176  {
3177  int i;
3178 
3179  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
3180  estate->es_param_exec_vals = (ParamExecData *)
3181  palloc0(i * sizeof(ParamExecData));
3182  while (--i >= 0)
3183  {
3184  /* copy value if any, but not execPlan link */
3185  estate->es_param_exec_vals[i].value =
3186  parentestate->es_param_exec_vals[i].value;
3187  estate->es_param_exec_vals[i].isnull =
3188  parentestate->es_param_exec_vals[i].isnull;
3189  }
3190  }
3191 
3192  /*
3193  * Each EState must have its own es_epqScanDone state, but if we have
3194  * nested EPQ checks they should share es_epqTuple arrays. This allows
3195  * sub-rechecks to inherit the values being examined by an outer recheck.
3196  */
3197  estate->es_epqScanDone = (bool *) palloc0(rtsize * sizeof(bool));
3198  if (parentestate->es_epqTuple != NULL)
3199  {
3200  estate->es_epqTuple = parentestate->es_epqTuple;
3201  estate->es_epqTupleSet = parentestate->es_epqTupleSet;
3202  }
3203  else
3204  {
3205  estate->es_epqTuple = (HeapTuple *)
3206  palloc0(rtsize * sizeof(HeapTuple));
3207  estate->es_epqTupleSet = (bool *)
3208  palloc0(rtsize * sizeof(bool));
3209  }
3210 
3211  /*
3212  * Each estate also has its own tuple table.
3213  */
3214  estate->es_tupleTable = NIL;
3215 
3216  /*
3217  * Initialize private state information for each SubPlan. We must do this
3218  * before running ExecInitNode on the main query tree, since
3219  * ExecInitSubPlan expects to be able to find these entries. Some of the
3220  * SubPlans might not be used in the part of the plan tree we intend to
3221  * run, but since it's not easy to tell which, we just initialize them
3222  * all.
3223  */
3224  Assert(estate->es_subplanstates == NIL);
3225  foreach(l, parentestate->es_plannedstmt->subplans)
3226  {
3227  Plan *subplan = (Plan *) lfirst(l);
3228  PlanState *subplanstate;
3229 
3230  subplanstate = ExecInitNode(subplan, estate, 0);
3231  estate->es_subplanstates = lappend(estate->es_subplanstates,
3232  subplanstate);
3233  }
3234 
3235  /*
3236  * Initialize the private state information for all the nodes in the part
3237  * of the plan tree we need to run. This opens files, allocates storage
3238  * and leaves us ready to start processing tuples.
3239  */
3240  epqstate->planstate = ExecInitNode(planTree, estate, 0);
3241 
3242  MemoryContextSwitchTo(oldcontext);
3243 }
List * paramExecTypes
Definition: plannodes.h:95
#define NIL
Definition: pg_list.h:69
HeapTuple * es_epqTuple
Definition: execnodes.h:558
JunkFilter * es_junkFilter
Definition: execnodes.h:484
CommandId es_output_cid
Definition: execnodes.h:487
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlannedStmt * es_plannedstmt
Definition: execnodes.h:481
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:479
Snapshot es_snapshot
Definition: execnodes.h:478
List * es_range_table
Definition: execnodes.h:480
PlanState * planstate
Definition: execnodes.h:993
ScanDirection es_direction
Definition: execnodes.h:477
ParamExecData * es_param_exec_vals
Definition: execnodes.h:518
MemoryContext es_query_cxt
Definition: execnodes.h:523
bool isnull
Definition: params.h:149
ResultRelInfo * es_result_relations
Definition: execnodes.h:490
int es_instrument
Definition: execnodes.h:533
EState * CreateExecutorState(void)
Definition: execUtils.c:80
List * lappend(List *list, void *datum)
Definition: list.c:128
List * es_tupleTable
Definition: execnodes.h:525
void * palloc0(Size size)
Definition: mcxt.c:955
int es_num_result_relations
Definition: execnodes.h:491
List * subplans
Definition: plannodes.h:84
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
bool * es_epqTupleSet
Definition: execnodes.h:559
List * es_subplanstates
Definition: execnodes.h:538
List * es_rowMarks
Definition: execnodes.h:527
void * palloc(Size size)
Definition: mcxt.c:924
int es_top_eflags
Definition: execnodes.h:532
int i
bool * es_epqScanDone
Definition: execnodes.h:560
Datum value
Definition: params.h:148
ParamListInfo es_param_list_info
Definition: execnodes.h:517
EState * estate
Definition: execnodes.h:992
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2433 of file execMain.c.

References AttributeNumberIsValid, ExecAuxRowMark::ctidAttNo, elog, ERROR, ExecFindJunkAttributeInTlist(), ExecRowMark::markType, palloc0(), ExecRowMark::prti, ROW_MARK_COPY, ExecAuxRowMark::rowmark, ExecRowMark::rowmarkId, ExecRowMark::rti, snprintf(), ExecAuxRowMark::toidAttNo, and ExecAuxRowMark::wholeAttNo.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

2434 {
2435  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2436  char resname[32];
2437 
2438  aerm->rowmark = erm;
2439 
2440  /* Look up the resjunk columns associated with this rowmark */
2441  if (erm->markType != ROW_MARK_COPY)
2442  {
2443  /* need ctid for all methods other than COPY */
2444  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2445  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2446  resname);
2447  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2448  elog(ERROR, "could not find junk %s column", resname);
2449  }
2450  else
2451  {
2452  /* need wholerow if COPY */
2453  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2454  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2455  resname);
2456  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2457  elog(ERROR, "could not find junk %s column", resname);
2458  }
2459 
2460  /* if child rel, need tableoid */
2461  if (erm->rti != erm->prti)
2462  {
2463  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2464  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2465  resname);
2466  if (!AttributeNumberIsValid(aerm->toidAttNo))
2467  elog(ERROR, "could not find junk %s column", resname);
2468  }
2469 
2470  return aerm;
2471 }
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:221
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
ExecRowMark * rowmark
Definition: execnodes.h:623
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:598
AttrNumber wholeAttNo
Definition: execnodes.h:626
Index prti
Definition: execnodes.h:599
Index rowmarkId
Definition: execnodes.h:600
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void * palloc0(Size size)
Definition: mcxt.c:955
RowMarkType markType
Definition: execnodes.h:601
AttrNumber toidAttNo
Definition: execnodes.h:625
#define elog
Definition: elog.h:219
AttrNumber ctidAttNo
Definition: execnodes.h:624

◆ ExecBuildSlotValueDescription()

static char * ExecBuildSlotValueDescription ( Oid  reloid,
TupleTableSlot slot,
TupleDesc  tupdesc,
Bitmapset modifiedCols,
int  maxfieldlen 
)
static

Definition at line 2246 of file execMain.c.

References ACL_SELECT, ACLCHECK_OK, appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), bms_is_member(), buf, check_enable_rls(), StringInfoData::data, FirstLowInvalidHeapAttributeNumber, getTypeOutputInfo(), GetUserId(), i, initStringInfo(), InvalidOid, NameStr, tupleDesc::natts, OidOutputFunctionCall(), pg_attribute_aclcheck(), pg_class_aclcheck(), pg_mbcliplen(), RLS_ENABLED, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TupleDescAttr, and val.

Referenced by ExecConstraints(), ExecPartitionCheckEmitError(), and ExecWithCheckOptions().

2251 {
2253  StringInfoData collist;
2254  bool write_comma = false;
2255  bool write_comma_collist = false;
2256  int i;
2257  AclResult aclresult;
2258  bool table_perm = false;
2259  bool any_perm = false;
2260 
2261  /*
2262  * Check if RLS is enabled and should be active for the relation; if so,
2263  * then don't return anything. Otherwise, go through normal permission
2264  * checks.
2265  */
2266  if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2267  return NULL;
2268 
2269  initStringInfo(&buf);
2270 
2271  appendStringInfoChar(&buf, '(');
2272 
2273  /*
2274  * Check if the user has permissions to see the row. Table-level SELECT
2275  * allows access to all columns. If the user does not have table-level
2276  * SELECT then we check each column and include those the user has SELECT
2277  * rights on. Additionally, we always include columns the user provided
2278  * data for.
2279  */
2280  aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2281  if (aclresult != ACLCHECK_OK)
2282  {
2283  /* Set up the buffer for the column list */
2284  initStringInfo(&collist);
2285  appendStringInfoChar(&collist, '(');
2286  }
2287  else
2288  table_perm = any_perm = true;
2289 
2290  /* Make sure the tuple is fully deconstructed */
2291  slot_getallattrs(slot);
2292 
2293  for (i = 0; i < tupdesc->natts; i++)
2294  {
2295  bool column_perm = false;
2296  char *val;
2297  int vallen;
2298  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2299 
2300  /* ignore dropped columns */
2301  if (att->attisdropped)
2302  continue;
2303 
2304  if (!table_perm)
2305  {
2306  /*
2307  * No table-level SELECT, so need to make sure they either have
2308  * SELECT rights on the column or that they have provided the data
2309  * for the column. If not, omit this column from the error
2310  * message.
2311  */
2312  aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2313  GetUserId(), ACL_SELECT);
2315  modifiedCols) || aclresult == ACLCHECK_OK)
2316  {
2317  column_perm = any_perm = true;
2318 
2319  if (write_comma_collist)
2320  appendStringInfoString(&collist, ", ");
2321  else
2322  write_comma_collist = true;
2323 
2324  appendStringInfoString(&collist, NameStr(att->attname));
2325  }
2326  }
2327 
2328  if (table_perm || column_perm)
2329  {
2330  if (slot->tts_isnull[i])
2331  val = "null";
2332  else
2333  {
2334  Oid foutoid;
2335  bool typisvarlena;
2336 
2337  getTypeOutputInfo(att->atttypid,
2338  &foutoid, &typisvarlena);
2339  val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2340  }
2341 
2342  if (write_comma)
2343  appendStringInfoString(&buf, ", ");
2344  else
2345  write_comma = true;
2346 
2347  /* truncate if needed */
2348  vallen = strlen(val);
2349  if (vallen <= maxfieldlen)
2350  appendStringInfoString(&buf, val);
2351  else
2352  {
2353  vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2354  appendBinaryStringInfo(&buf, val, vallen);
2355  appendStringInfoString(&buf, "...");
2356  }
2357  }
2358  }
2359 
2360  /* If we end up with zero columns being returned, then return NULL. */
2361  if (!any_perm)
2362  return NULL;
2363 
2364  appendStringInfoChar(&buf, ')');
2365 
2366  if (!table_perm)
2367  {
2368  appendStringInfoString(&collist, ") = ");
2369  appendStringInfoString(&collist, buf.data);
2370 
2371  return collist.data;
2372  }
2373 
2374  return buf.data;
2375 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4513
Oid GetUserId(void)
Definition: miscinit.c:379
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
Datum * tts_values
Definition: tuptable.h:130
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:82
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:820
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
bool * tts_isnull
Definition: tuptable.h:132
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
void slot_getallattrs(TupleTableSlot *slot)
Definition: heaptuple.c:1612
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
AclResult
Definition: acl.h:178
#define ACL_SELECT
Definition: parsenodes.h:75
#define InvalidOid
Definition: postgres_ext.h:36
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4627
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1833
int i
#define NameStr(name)
Definition: c.h:576
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:208
long val
Definition: informix.c:689

◆ ExecCheckRTEPerms()

static bool ExecCheckRTEPerms ( RangeTblEntry rte)
static

Definition at line 605 of file execMain.c.

References ACL_INSERT, ACL_SELECT, ACL_UPDATE, ACLCHECK_OK, ACLMASK_ALL, ACLMASK_ANY, bms_is_empty(), bms_next_member(), RangeTblEntry::checkAsUser, ExecCheckRTEPermsModified(), FirstLowInvalidHeapAttributeNumber, GetUserId(), RangeTblEntry::insertedCols, InvalidAttrNumber, pg_attribute_aclcheck(), pg_attribute_aclcheck_all(), pg_class_aclmask(), RangeTblEntry::relid, RangeTblEntry::requiredPerms, RTE_RELATION, RangeTblEntry::rtekind, RangeTblEntry::selectedCols, and RangeTblEntry::updatedCols.

Referenced by ExecCheckRTPerms().

606 {
607  AclMode requiredPerms;
608  AclMode relPerms;
609  AclMode remainingPerms;
610  Oid relOid;
611  Oid userid;
612 
613  /*
614  * Only plain-relation RTEs need to be checked here. Function RTEs are
615  * checked when the function is prepared for execution. Join, subquery,
616  * and special RTEs need no checks.
617  */
618  if (rte->rtekind != RTE_RELATION)
619  return true;
620 
621  /*
622  * No work if requiredPerms is empty.
623  */
624  requiredPerms = rte->requiredPerms;
625  if (requiredPerms == 0)
626  return true;
627 
628  relOid = rte->relid;
629 
630  /*
631  * userid to check as: current user unless we have a setuid indication.
632  *
633  * Note: GetUserId() is presently fast enough that there's no harm in
634  * calling it separately for each RTE. If that stops being true, we could
635  * call it once in ExecCheckRTPerms and pass the userid down from there.
636  * But for now, no need for the extra clutter.
637  */
638  userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
639 
640  /*
641  * We must have *all* the requiredPerms bits, but some of the bits can be
642  * satisfied from column-level rather than relation-level permissions.
643  * First, remove any bits that are satisfied by relation permissions.
644  */
645  relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL);
646  remainingPerms = requiredPerms & ~relPerms;
647  if (remainingPerms != 0)
648  {
649  int col = -1;
650 
651  /*
652  * If we lack any permissions that exist only as relation permissions,
653  * we can fail straight away.
654  */
655  if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE))
656  return false;
657 
658  /*
659  * Check to see if we have the needed privileges at column level.
660  *
661  * Note: failures just report a table-level error; it would be nicer
662  * to report a column-level error if we have some but not all of the
663  * column privileges.
664  */
665  if (remainingPerms & ACL_SELECT)
666  {
667  /*
668  * When the query doesn't explicitly reference any columns (for
669  * example, SELECT COUNT(*) FROM table), allow the query if we
670  * have SELECT on any column of the rel, as per SQL spec.
671  */
672  if (bms_is_empty(rte->selectedCols))
673  {
674  if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
676  return false;
677  }
678 
679  while ((col = bms_next_member(rte->selectedCols, col)) >= 0)
680  {
681  /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
683 
684  if (attno == InvalidAttrNumber)
685  {
686  /* Whole-row reference, must have priv on all cols */
687  if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
689  return false;
690  }
691  else
692  {
693  if (pg_attribute_aclcheck(relOid, attno, userid,
694  ACL_SELECT) != ACLCHECK_OK)
695  return false;
696  }
697  }
698  }
699 
700  /*
701  * Basically the same for the mod columns, for both INSERT and UPDATE
702  * privilege as specified by remainingPerms.
703  */
704  if (remainingPerms & ACL_INSERT && !ExecCheckRTEPermsModified(relOid,
705  userid,
706  rte->insertedCols,
707  ACL_INSERT))
708  return false;
709 
710  if (remainingPerms & ACL_UPDATE && !ExecCheckRTEPermsModified(relOid,
711  userid,
712  rte->updatedCols,
713  ACL_UPDATE))
714  return false;
715  }
716  return true;
717 }
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4513
Oid GetUserId(void)
Definition: miscinit.c:379
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1075
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
AclMode requiredPerms
Definition: parsenodes.h:1070
unsigned int Oid
Definition: postgres_ext.h:31
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3827
uint32 AclMode
Definition: parsenodes.h:72
Bitmapset * selectedCols
Definition: parsenodes.h:1072
static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms)
Definition: execMain.c:725
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
#define ACL_UPDATE
Definition: parsenodes.h:76
#define ACL_SELECT
Definition: parsenodes.h:75
Bitmapset * updatedCols
Definition: parsenodes.h:1074
#define ACL_INSERT
Definition: parsenodes.h:74
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4542
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:962
Bitmapset * insertedCols
Definition: parsenodes.h:1073
int16 AttrNumber
Definition: attnum.h:21

◆ ExecCheckRTEPermsModified()

static bool ExecCheckRTEPermsModified ( Oid  relOid,
Oid  userid,
Bitmapset modifiedCols,
AclMode  requiredPerms 
)
static

Definition at line 725 of file execMain.c.

References ACLCHECK_OK, ACLMASK_ANY, bms_is_empty(), bms_next_member(), elog, ERROR, FirstLowInvalidHeapAttributeNumber, InvalidAttrNumber, pg_attribute_aclcheck(), and pg_attribute_aclcheck_all().

Referenced by ExecCheckRTEPerms().

727 {
728  int col = -1;
729 
730  /*
731  * When the query doesn't explicitly update any columns, allow the query
732  * if we have permission on any column of the rel. This is to handle
733  * SELECT FOR UPDATE as well as possible corner cases in UPDATE.
734  */
735  if (bms_is_empty(modifiedCols))
736  {
737  if (pg_attribute_aclcheck_all(relOid, userid, requiredPerms,
739  return false;
740  }
741 
742  while ((col = bms_next_member(modifiedCols, col)) >= 0)
743  {
744  /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
746 
747  if (attno == InvalidAttrNumber)
748  {
749  /* whole-row reference can't happen here */
750  elog(ERROR, "whole-row update is not implemented");
751  }
752  else
753  {
754  if (pg_attribute_aclcheck(relOid, attno, userid,
755  requiredPerms) != ACLCHECK_OK)
756  return false;
757  }
758  }
759  return true;
760 }
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4513
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1075
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define ERROR
Definition: elog.h:43
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4542
#define InvalidAttrNumber
Definition: attnum.h:23
#define elog
Definition: elog.h:219
int16 AttrNumber
Definition: attnum.h:21

◆ ExecCheckRTPerms()

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

Definition at line 574 of file execMain.c.

References aclcheck_error(), ACLCHECK_NO_PRIV, Assert, ExecCheckRTEPerms(), ExecutorCheckPerms_hook, get_rel_name(), get_rel_relkind(), get_relkind_objtype(), lfirst, RangeTblEntry::relid, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by DoCopy(), InitPlan(), intorel_startup(), and RI_Initial_Check().

575 {
576  ListCell *l;
577  bool result = true;
578 
579  foreach(l, rangeTable)
580  {
581  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
582 
583  result = ExecCheckRTEPerms(rte);
584  if (!result)
585  {
586  Assert(rte->rtekind == RTE_RELATION);
587  if (ereport_on_violation)
589  get_rel_name(rte->relid));
590  return false;
591  }
592  }
593 
595  result = (*ExecutorCheckPerms_hook) (rangeTable,
596  ereport_on_violation);
597  return result;
598 }
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
static bool ExecCheckRTEPerms(RangeTblEntry *rte)
Definition: execMain.c:605
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:76
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
RTEKind rtekind
Definition: parsenodes.h:962
ObjectType get_relkind_objtype(char relkind)
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730

◆ ExecCheckXactReadOnly()

static void ExecCheckXactReadOnly ( PlannedStmt plannedstmt)
static

Definition at line 772 of file execMain.c.

References ACL_SELECT, CMD_SELECT, PlannedStmt::commandType, CreateCommandTag(), get_rel_namespace(), PlannedStmt::hasModifyingCTE, isTempNamespace(), lfirst, PreventCommandIfParallelMode(), PreventCommandIfReadOnly(), RangeTblEntry::relid, RangeTblEntry::requiredPerms, PlannedStmt::rtable, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by standard_ExecutorStart().

773 {
774  ListCell *l;
775 
776  /*
777  * Fail if write permissions are requested in parallel mode for table
778  * (temp or non-temp), otherwise fail for any non-temp table.
779  */
780  foreach(l, plannedstmt->rtable)
781  {
782  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
783 
784  if (rte->rtekind != RTE_RELATION)
785  continue;
786 
787  if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
788  continue;
789 
791  continue;
792 
794  }
795 
796  if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
798 }
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:257
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1754
Definition: nodes.h:516
AclMode requiredPerms
Definition: parsenodes.h:1070
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3137
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2070
CmdType commandType
Definition: plannodes.h:46
#define ACL_SELECT
Definition: parsenodes.h:75
#define lfirst(lc)
Definition: pg_list.h:106
bool hasModifyingCTE
Definition: plannodes.h:52
List * rtable
Definition: plannodes.h:66
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:239
RTEKind rtekind
Definition: parsenodes.h:962

◆ ExecCleanUpTriggerState()

void ExecCleanUpTriggerState ( EState estate)

Definition at line 1474 of file execMain.c.

References EState::es_trig_target_relations, ExecCloseIndices(), heap_close, lfirst, NoLock, and ResultRelInfo::ri_RelationDesc.

Referenced by afterTriggerInvokeEvents(), CopyFrom(), EvalPlanQualEnd(), and ExecEndPlan().

1475 {
1476  ListCell *l;
1477 
1478  foreach(l, estate->es_trig_target_relations)
1479  {
1480  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1481 
1482  /* Close indices and then the relation itself */
1483  ExecCloseIndices(resultRelInfo);
1484  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1485  }
1486 }
Relation ri_RelationDesc
Definition: execnodes.h:397
#define heap_close(r, l)
Definition: heapam.h:97
#define NoLock
Definition: lockdefs.h:34
List * es_trig_target_relations
Definition: execnodes.h:511
#define lfirst(lc)
Definition: pg_list.h:106
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:224

◆ ExecConstraints()

void ExecConstraints ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate 
)

Definition at line 1971 of file execMain.c.

References Assert, bms_union(), tupleDesc::constr, convert_tuples_by_name(), do_convert_tuple(), ereport, errcode(), errdetail(), errmsg(), ERROR, errtablecol(), errtableconstraint(), ExecBuildSlotValueDescription(), ExecFetchSlotTuple(), ExecRelCheck(), ExecSetSlotDescriptor(), ExecStoreTuple(), GetInsertedColumns, gettext_noop, GetUpdatedColumns, tupleConstr::has_not_null, InvalidBuffer, NameStr, tupleDesc::natts, tupleConstr::num_check, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ResultRelInfo::ri_PartitionCheck, ResultRelInfo::ri_PartitionRoot, ResultRelInfo::ri_RelationDesc, slot_attisnull(), and TupleDescAttr.

Referenced by CopyFrom(), ExecInsert(), ExecSimpleRelationInsert(), ExecSimpleRelationUpdate(), and ExecUpdate().

1973 {
1974  Relation rel = resultRelInfo->ri_RelationDesc;
1975  TupleDesc tupdesc = RelationGetDescr(rel);
1976  TupleConstr *constr = tupdesc->constr;
1977  Bitmapset *modifiedCols;
1978  Bitmapset *insertedCols;
1979  Bitmapset *updatedCols;
1980 
1981  Assert(constr || resultRelInfo->ri_PartitionCheck);
1982 
1983  if (constr && constr->has_not_null)
1984  {
1985  int natts = tupdesc->natts;
1986  int attrChk;
1987 
1988  for (attrChk = 1; attrChk <= natts; attrChk++)
1989  {
1990  Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
1991 
1992  if (att->attnotnull && slot_attisnull(slot, attrChk))
1993  {
1994  char *val_desc;
1995  Relation orig_rel = rel;
1996  TupleDesc orig_tupdesc = RelationGetDescr(rel);
1997 
1998  /*
1999  * If the tuple has been routed, it's been converted to the
2000  * partition's rowtype, which might differ from the root
2001  * table's. We must convert it back to the root table's
2002  * rowtype so that val_desc shown error message matches the
2003  * input tuple.
2004  */
2005  if (resultRelInfo->ri_PartitionRoot)
2006  {
2007  HeapTuple tuple = ExecFetchSlotTuple(slot);
2008  TupleConversionMap *map;
2009 
2010  rel = resultRelInfo->ri_PartitionRoot;
2011  tupdesc = RelationGetDescr(rel);
2012  /* a reverse map */
2013  map = convert_tuples_by_name(orig_tupdesc, tupdesc,
2014  gettext_noop("could not convert row type"));
2015  if (map != NULL)
2016  {
2017  tuple = do_convert_tuple(tuple, map);
2018  ExecSetSlotDescriptor(slot, tupdesc);
2019  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2020  }
2021  }
2022 
2023  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2024  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2025  modifiedCols = bms_union(insertedCols, updatedCols);
2027  slot,
2028  tupdesc,
2029  modifiedCols,
2030  64);
2031 
2032  ereport(ERROR,
2033  (errcode(ERRCODE_NOT_NULL_VIOLATION),
2034  errmsg("null value in column \"%s\" violates not-null constraint",
2035  NameStr(att->attname)),
2036  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2037  errtablecol(orig_rel, attrChk)));
2038  }
2039  }
2040  }
2041 
2042  if (constr && constr->num_check > 0)
2043  {
2044  const char *failed;
2045 
2046  if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2047  {
2048  char *val_desc;
2049  Relation orig_rel = rel;
2050 
2051  /* See the comment above. */
2052  if (resultRelInfo->ri_PartitionRoot)
2053  {
2054  HeapTuple tuple = ExecFetchSlotTuple(slot);
2055  TupleDesc old_tupdesc = RelationGetDescr(rel);
2056  TupleConversionMap *map;
2057 
2058  rel = resultRelInfo->ri_PartitionRoot;
2059  tupdesc = RelationGetDescr(rel);
2060  /* a reverse map */
2061  map = convert_tuples_by_name(old_tupdesc, tupdesc,
2062  gettext_noop("could not convert row type"));
2063  if (map != NULL)
2064  {
2065  tuple = do_convert_tuple(tuple, map);
2066  ExecSetSlotDescriptor(slot, tupdesc);
2067  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2068  }
2069  }
2070 
2071  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2072  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2073  modifiedCols = bms_union(insertedCols, updatedCols);
2075  slot,
2076  tupdesc,
2077  modifiedCols,
2078  64);
2079  ereport(ERROR,
2080  (errcode(ERRCODE_CHECK_VIOLATION),
2081  errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2082  RelationGetRelationName(orig_rel), failed),
2083  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2084  errtableconstraint(orig_rel, failed)));
2085  }
2086  }
2087 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:112
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
Relation ri_RelationDesc
Definition: execnodes.h:397
#define RelationGetDescr(relation)
Definition: rel.h:433
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
Relation ri_PartitionRoot
Definition: execnodes.h:460
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:1036
int errcode(int sqlerrcode)
Definition: elog.c:575
int natts
Definition: tupdesc.h:82
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5317
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2246
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:441
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
#define ereport(elevel, rest)
Definition: elog.h:122
bool has_not_null
Definition: tupdesc.h:46
TupleConversionMap * convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc, const char *msg)
Definition: tupconvert.c:210
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:281
List * ri_PartitionCheck
Definition: execnodes.h:454
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1798
bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1703
#define Assert(condition)
Definition: c.h:699
int errtablecol(Relation rel, int attnum)
Definition: relcache.c:5280
TupleConstr * constr
Definition: tupdesc.h:87
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:661
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:576
uint16 num_check
Definition: tupdesc.h:45
#define RelationGetRelid(relation)
Definition: rel.h:407
#define GetInsertedColumns(relinfo, estate)
Definition: execMain.c:110

◆ ExecContextForcesOids()

bool ExecContextForcesOids ( PlanState planstate,
bool hasoids 
)

Definition at line 1521 of file execMain.c.

References EState::es_result_relation_info, EState::es_top_eflags, EXEC_FLAG_WITH_OIDS, EXEC_FLAG_WITHOUT_OIDS, RelationData::rd_rel, ResultRelInfo::ri_RelationDesc, and PlanState::state.

Referenced by ExecInitResultTupleSlotTL(), and tlist_matches_tupdesc().

1522 {
1523  ResultRelInfo *ri = planstate->state->es_result_relation_info;
1524 
1525  if (ri != NULL)
1526  {
1527  Relation rel = ri->ri_RelationDesc;
1528 
1529  if (rel != NULL)
1530  {
1531  *hasoids = rel->rd_rel->relhasoids;
1532  return true;
1533  }
1534  }
1535 
1536  if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS)
1537  {
1538  *hasoids = true;
1539  return true;
1540  }
1541  if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS)
1542  {
1543  *hasoids = false;
1544  return true;
1545  }
1546 
1547  return false;
1548 }
Relation ri_RelationDesc
Definition: execnodes.h:397
EState * state
Definition: execnodes.h:914
Form_pg_class rd_rel
Definition: rel.h:84
#define EXEC_FLAG_WITHOUT_OIDS
Definition: executor.h:64
#define EXEC_FLAG_WITH_OIDS
Definition: executor.h:63
int es_top_eflags
Definition: execnodes.h:532
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:492

◆ ExecEndPlan()

static void ExecEndPlan ( PlanState planstate,
EState estate 
)
static

Definition at line 1603 of file execMain.c.

References EState::es_num_result_relations, EState::es_num_root_result_relations, EState::es_result_relations, EState::es_root_result_relations, EState::es_rowMarks, EState::es_subplanstates, EState::es_tupleTable, ExecCleanUpTriggerState(), ExecCloseIndices(), ExecEndNode(), ExecResetTupleTable(), heap_close, i, lfirst, NoLock, ExecRowMark::relation, and ResultRelInfo::ri_RelationDesc.

Referenced by standard_ExecutorEnd().

1604 {
1605  ResultRelInfo *resultRelInfo;
1606  int i;
1607  ListCell *l;
1608 
1609  /*
1610  * shut down the node-type-specific query processing
1611  */
1612  ExecEndNode(planstate);
1613 
1614  /*
1615  * for subplans too
1616  */
1617  foreach(l, estate->es_subplanstates)
1618  {
1619  PlanState *subplanstate = (PlanState *) lfirst(l);
1620 
1621  ExecEndNode(subplanstate);
1622  }
1623 
1624  /*
1625  * destroy the executor's tuple table. Actually we only care about
1626  * releasing buffer pins and tupdesc refcounts; there's no need to pfree
1627  * the TupleTableSlots, since the containing memory context is about to go
1628  * away anyway.
1629  */
1630  ExecResetTupleTable(estate->es_tupleTable, false);
1631 
1632  /*
1633  * close the result relation(s) if any, but hold locks until xact commit.
1634  */
1635  resultRelInfo = estate->es_result_relations;
1636  for (i = estate->es_num_result_relations; i > 0; i--)
1637  {
1638  /* Close indices and then the relation itself */
1639  ExecCloseIndices(resultRelInfo);
1640  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1641  resultRelInfo++;
1642  }
1643 
1644  /* Close the root target relation(s). */
1645  resultRelInfo = estate->es_root_result_relations;
1646  for (i = estate->es_num_root_result_relations; i > 0; i--)
1647  {
1648  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1649  resultRelInfo++;
1650  }
1651 
1652  /* likewise close any trigger target relations */
1653  ExecCleanUpTriggerState(estate);
1654 
1655  /*
1656  * close any relations selected FOR [KEY] UPDATE/SHARE, again keeping
1657  * locks
1658  */
1659  foreach(l, estate->es_rowMarks)
1660  {
1661  ExecRowMark *erm = (ExecRowMark *) lfirst(l);
1662 
1663  if (erm->relation)
1664  heap_close(erm->relation, NoLock);
1665  }
1666 }
Relation ri_RelationDesc
Definition: execnodes.h:397
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:538
Relation relation
Definition: execnodes.h:596
#define heap_close(r, l)
Definition: heapam.h:97
#define NoLock
Definition: lockdefs.h:34
ResultRelInfo * es_result_relations
Definition: execnodes.h:490
int es_num_root_result_relations
Definition: execnodes.h:502
List * es_tupleTable
Definition: execnodes.h:525
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:186
int es_num_result_relations
Definition: execnodes.h:491
#define lfirst(lc)
Definition: pg_list.h:106
List * es_subplanstates
Definition: execnodes.h:538
List * es_rowMarks
Definition: execnodes.h:527
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1474
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:501
int i
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:224

◆ ExecFindRowMark()

ExecRowMark* ExecFindRowMark ( EState estate,
Index  rti,
bool  missing_ok 
)

Definition at line 2409 of file execMain.c.

References elog, ERROR, EState::es_rowMarks, lfirst, and ExecRowMark::rti.

Referenced by ExecInitLockRows(), ExecInitModifyTable(), and ExecOpenScanRelation().

2410 {
2411  ListCell *lc;
2412 
2413  foreach(lc, estate->es_rowMarks)
2414  {
2415  ExecRowMark *erm = (ExecRowMark *) lfirst(lc);
2416 
2417  if (erm->rti == rti)
2418  return erm;
2419  }
2420  if (!missing_ok)
2421  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2422  return NULL;
2423 }
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:598
#define lfirst(lc)
Definition: pg_list.h:106
List * es_rowMarks
Definition: execnodes.h:527
#define elog
Definition: elog.h:219

◆ ExecGetTriggerResultRel()

ResultRelInfo* ExecGetTriggerResultRel ( EState estate,
Oid  relid 
)

Definition at line 1392 of file execMain.c.

References EState::es_instrument, EState::es_num_result_relations, EState::es_num_root_result_relations, EState::es_query_cxt, EState::es_result_relations, EState::es_root_result_relations, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, heap_open(), InitResultRelInfo(), lappend(), lfirst, makeNode, MemoryContextSwitchTo(), NoLock, RelationGetRelid, and ResultRelInfo::ri_RelationDesc.

Referenced by afterTriggerInvokeEvents().

1393 {
1394  ResultRelInfo *rInfo;
1395  int nr;
1396  ListCell *l;
1397  Relation rel;
1398  MemoryContext oldcontext;
1399 
1400  /* First, search through the query result relations */
1401  rInfo = estate->es_result_relations;
1402  nr = estate->es_num_result_relations;
1403  while (nr > 0)
1404  {
1405  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1406  return rInfo;
1407  rInfo++;
1408  nr--;
1409  }
1410  /* Second, search through the root result relations, if any */
1411  rInfo = estate->es_root_result_relations;
1412  nr = estate->es_num_root_result_relations;
1413  while (nr > 0)
1414  {
1415  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1416  return rInfo;
1417  rInfo++;
1418  nr--;
1419  }
1420 
1421  /*
1422  * Third, search through the result relations that were created during
1423  * tuple routing, if any.
1424  */
1425  foreach(l, estate->es_tuple_routing_result_relations)
1426  {
1427  rInfo = (ResultRelInfo *) lfirst(l);
1428  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1429  return rInfo;
1430  }
1431  /* Nope, but maybe we already made an extra ResultRelInfo for it */
1432  foreach(l, estate->es_trig_target_relations)
1433  {
1434  rInfo = (ResultRelInfo *) lfirst(l);
1435  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1436  return rInfo;
1437  }
1438  /* Nope, so we need a new one */
1439 
1440  /*
1441  * Open the target relation's relcache entry. We assume that an
1442  * appropriate lock is still held by the backend from whenever the trigger
1443  * event got queued, so we need take no new lock here. Also, we need not
1444  * recheck the relkind, so no need for CheckValidResultRel.
1445  */
1446  rel = heap_open(relid, NoLock);
1447 
1448  /*
1449  * Make the new entry in the right context.
1450  */
1451  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1452  rInfo = makeNode(ResultRelInfo);
1453  InitResultRelInfo(rInfo,
1454  rel,
1455  0, /* dummy rangetable index */
1456  NULL,
1457  estate->es_instrument);
1458  estate->es_trig_target_relations =
1459  lappend(estate->es_trig_target_relations, rInfo);
1460  MemoryContextSwitchTo(oldcontext);
1461 
1462  /*
1463  * Currently, we don't need any index information in ResultRelInfos used
1464  * only for triggers, so no need to call ExecOpenIndices.
1465  */
1466 
1467  return rInfo;
1468 }
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1305
Relation ri_RelationDesc
Definition: execnodes.h:397
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:523
#define NoLock
Definition: lockdefs.h:34
ResultRelInfo * es_result_relations
Definition: execnodes.h:490
int es_instrument
Definition: execnodes.h:533
List * lappend(List *list, void *datum)
Definition: list.c:128
int es_num_root_result_relations
Definition: execnodes.h:502
List * es_trig_target_relations
Definition: execnodes.h:511
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
int es_num_result_relations
Definition: execnodes.h:491
List * es_tuple_routing_result_relations
Definition: execnodes.h:508
#define makeNode(_type_)
Definition: nodes.h:564
#define lfirst(lc)
Definition: pg_list.h:106
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:501
#define RelationGetRelid(relation)
Definition: rel.h:407

◆ ExecPartitionCheck()

bool ExecPartitionCheck ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate,
bool  emitError 
)

Definition at line 1864 of file execMain.c.

References ExprContext::ecxt_scantuple, ExecCheck(), ExecPartitionCheckEmitError(), ExecPrepareCheck(), GetPerTupleExprContext, ResultRelInfo::ri_PartitionCheck, ResultRelInfo::ri_PartitionCheckExpr, and success.

Referenced by CopyFrom(), ExecFindPartition(), ExecInsert(), ExecSimpleRelationInsert(), ExecSimpleRelationUpdate(), and ExecUpdate().

1866 {
1867  ExprContext *econtext;
1868  bool success;
1869 
1870  /*
1871  * If first time through, build expression state tree for the partition
1872  * check expression. Keep it in the per-query memory context so they'll
1873  * survive throughout the query.
1874  */
1875  if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1876  {
1877  List *qual = resultRelInfo->ri_PartitionCheck;
1878 
1879  resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1880  }
1881 
1882  /*
1883  * We will use the EState's per-tuple context for evaluating constraint
1884  * expressions (creating it if it's not already there).
1885  */
1886  econtext = GetPerTupleExprContext(estate);
1887 
1888  /* Arrange for econtext's scan tuple to be the tuple under test */
1889  econtext->ecxt_scantuple = slot;
1890 
1891  /*
1892  * As in case of the catalogued constraints, we treat a NULL result as
1893  * success here, not a failure.
1894  */
1895  success = ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
1896 
1897  /* if asked to emit error, don't actually return on failure */
1898  if (!success && emitError)
1899  ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
1900 
1901  return success;
1902 }
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:539
ExprState * ri_PartitionCheckExpr
Definition: execnodes.h:457
#define GetPerTupleExprContext(estate)
Definition: executor.h:488
static bool success
void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1909
List * ri_PartitionCheck
Definition: execnodes.h:454
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:218
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:595
Definition: pg_list.h:45

◆ ExecPartitionCheckEmitError()

void ExecPartitionCheckEmitError ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate 
)

Definition at line 1909 of file execMain.c.

References bms_union(), convert_tuples_by_name(), do_convert_tuple(), ereport, errcode(), errdetail(), errmsg(), ERROR, ExecBuildSlotValueDescription(), ExecFetchSlotTuple(), ExecSetSlotDescriptor(), ExecStoreTuple(), GetInsertedColumns, gettext_noop, GetUpdatedColumns, InvalidBuffer, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ResultRelInfo::ri_PartitionRoot, and ResultRelInfo::ri_RelationDesc.

Referenced by ExecPartitionCheck(), and ExecUpdate().

1912 {
1913  Relation rel = resultRelInfo->ri_RelationDesc;
1914  Relation orig_rel = rel;
1915  TupleDesc tupdesc = RelationGetDescr(rel);
1916  char *val_desc;
1917  Bitmapset *modifiedCols;
1918  Bitmapset *insertedCols;
1919  Bitmapset *updatedCols;
1920 
1921  /*
1922  * Need to first convert the tuple to the root partitioned table's row
1923  * type. For details, check similar comments in ExecConstraints().
1924  */
1925  if (resultRelInfo->ri_PartitionRoot)
1926  {
1927  HeapTuple tuple = ExecFetchSlotTuple(slot);
1928  TupleDesc old_tupdesc = RelationGetDescr(rel);
1929  TupleConversionMap *map;
1930 
1931  rel = resultRelInfo->ri_PartitionRoot;
1932  tupdesc = RelationGetDescr(rel);
1933  /* a reverse map */
1934  map = convert_tuples_by_name(old_tupdesc, tupdesc,
1935  gettext_noop("could not convert row type"));
1936  if (map != NULL)
1937  {
1938  tuple = do_convert_tuple(tuple, map);
1939  ExecSetSlotDescriptor(slot, tupdesc);
1940  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
1941  }
1942  }
1943 
1944  insertedCols = GetInsertedColumns(resultRelInfo, estate);
1945  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
1946  modifiedCols = bms_union(insertedCols, updatedCols);
1948  slot,
1949  tupdesc,
1950  modifiedCols,
1951  64);
1952  ereport(ERROR,
1953  (errcode(ERRCODE_CHECK_VIOLATION),
1954  errmsg("new row for relation \"%s\" violates partition constraint",
1955  RelationGetRelationName(orig_rel)),
1956  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
1957 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:112
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
Relation ri_RelationDesc
Definition: execnodes.h:397
#define RelationGetDescr(relation)
Definition: rel.h:433
Relation ri_PartitionRoot
Definition: execnodes.h:460
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:1036
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2246
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define ereport(elevel, rest)
Definition: elog.h:122
TupleConversionMap * convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc, const char *msg)
Definition: tupconvert.c:210
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:281
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:661
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RelationGetRelid(relation)
Definition: rel.h:407
#define GetInsertedColumns(relinfo, estate)
Definition: execMain.c:110

◆ ExecPostprocessPlan()

static void ExecPostprocessPlan ( EState estate)
static

Definition at line 1557 of file execMain.c.

References EState::es_auxmodifytables, EState::es_direction, ExecProcNode(), ForwardScanDirection, lfirst, ResetPerTupleExprContext, and TupIsNull.

Referenced by standard_ExecutorFinish().

1558 {
1559  ListCell *lc;
1560 
1561  /*
1562  * Make sure nodes run forward.
1563  */
1565 
1566  /*
1567  * Run any secondary ModifyTable nodes to completion, in case the main
1568  * query did not fetch all rows from them. (We do this to ensure that
1569  * such nodes have predictable results.)
1570  */
1571  foreach(lc, estate->es_auxmodifytables)
1572  {
1573  PlanState *ps = (PlanState *) lfirst(lc);
1574 
1575  for (;;)
1576  {
1577  TupleTableSlot *slot;
1578 
1579  /* Reset the per-output-tuple exprcontext each time */
1580  ResetPerTupleExprContext(estate);
1581 
1582  slot = ExecProcNode(ps);
1583 
1584  if (TupIsNull(slot))
1585  break;
1586  }
1587  }
1588 }
#define ResetPerTupleExprContext(estate)
Definition: executor.h:497
ScanDirection es_direction
Definition: execnodes.h:477
#define TupIsNull(slot)
Definition: tuptable.h:146
List * es_auxmodifytables
Definition: execnodes.h:540
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:232
#define lfirst(lc)
Definition: pg_list.h:106

◆ ExecRelCheck()

static const char* ExecRelCheck ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate 
)
static

Definition at line 1798 of file execMain.c.

References constrCheck::ccname, tupleConstr::check, tupleDesc::constr, ExprContext::ecxt_scantuple, EState::es_query_cxt, ExecCheck(), ExecPrepareExpr(), GetPerTupleExprContext, i, MemoryContextSwitchTo(), tupleConstr::num_check, palloc(), RelationData::rd_att, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_RelationDesc, and stringToNode().

Referenced by ExecConstraints().

1800 {
1801  Relation rel = resultRelInfo->ri_RelationDesc;
1802  int ncheck = rel->rd_att->constr->num_check;
1803  ConstrCheck *check = rel->rd_att->constr->check;
1804  ExprContext *econtext;
1805  MemoryContext oldContext;
1806  int i;
1807 
1808  /*
1809  * If first time through for this result relation, build expression
1810  * nodetrees for rel's constraint expressions. Keep them in the per-query
1811  * memory context so they'll survive throughout the query.
1812  */
1813  if (resultRelInfo->ri_ConstraintExprs == NULL)
1814  {
1815  oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
1816  resultRelInfo->ri_ConstraintExprs =
1817  (ExprState **) palloc(ncheck * sizeof(ExprState *));
1818  for (i = 0; i < ncheck; i++)
1819  {
1820  Expr *checkconstr;
1821 
1822  checkconstr = stringToNode(check[i].ccbin);
1823  resultRelInfo->ri_ConstraintExprs[i] =
1824  ExecPrepareExpr(checkconstr, estate);
1825  }
1826  MemoryContextSwitchTo(oldContext);
1827  }
1828 
1829  /*
1830  * We will use the EState's per-tuple context for evaluating constraint
1831  * expressions (creating it if it's not already there).
1832  */
1833  econtext = GetPerTupleExprContext(estate);
1834 
1835  /* Arrange for econtext's scan tuple to be the tuple under test */
1836  econtext->ecxt_scantuple = slot;
1837 
1838  /* And evaluate the constraints */
1839  for (i = 0; i < ncheck; i++)
1840  {
1841  ExprState *checkconstr = resultRelInfo->ri_ConstraintExprs[i];
1842 
1843  /*
1844  * NOTE: SQL specifies that a NULL result from a constraint expression
1845  * is not to be treated as a failure. Therefore, use ExecCheck not
1846  * ExecQual.
1847  */
1848  if (!ExecCheck(checkconstr, econtext))
1849  return check[i].ccname;
1850  }
1851 
1852  /* NULL result means no error */
1853  return NULL;
1854 }
void * stringToNode(char *str)
Definition: read.c:39
Relation ri_RelationDesc
Definition: execnodes.h:397
char * ccname
Definition: tupdesc.h:32
ConstrCheck * check
Definition: tupdesc.h:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:488
#define GetPerTupleExprContext(estate)
Definition: executor.h:488
MemoryContext es_query_cxt
Definition: execnodes.h:523
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:436
TupleDesc rd_att
Definition: rel.h:85
TupleConstr * constr
Definition: tupdesc.h:87
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:218
void * palloc(Size size)
Definition: mcxt.c:924
int i
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:595
uint16 num_check
Definition: tupdesc.h:45

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2383 of file execMain.c.

References bms_overlap(), GetUpdatedColumns, INDEX_ATTR_BITMAP_KEY, LockTupleExclusive, LockTupleNoKeyExclusive, RelationGetIndexAttrBitmap(), and ResultRelInfo::ri_RelationDesc.

Referenced by ExecBRUpdateTriggers(), and ExecOnConflictUpdate().

2384 {
2385  Bitmapset *keyCols;
2386  Bitmapset *updatedCols;
2387 
2388  /*
2389  * Compute lock mode to use. If columns that are part of the key have not
2390  * been modified, then we can use a weaker lock, allowing for better
2391  * concurrency.
2392  */
2393  updatedCols = GetUpdatedColumns(relinfo, estate);
2394  keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2396 
2397  if (bms_overlap(keyCols, updatedCols))
2398  return LockTupleExclusive;
2399 
2400  return LockTupleNoKeyExclusive;
2401 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:112
Relation ri_RelationDesc
Definition: execnodes.h:397
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:509
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:4829

◆ ExecutePlan()

static void ExecutePlan ( EState estate,
PlanState planstate,
bool  use_parallel_mode,
CmdType  operation,
bool  sendTuples,
uint64  numberTuples,
ScanDirection  direction,
DestReceiver dest,
bool  execute_once 
)
static

Definition at line 1681 of file execMain.c.

References CMD_SELECT, EnterParallelMode(), EState::es_direction, EState::es_junkFilter, EState::es_processed, EState::es_use_parallel_mode, ExecFilterJunk(), ExecProcNode(), ExecShutdownNode(), ExitParallelMode(), _DestReceiver::receiveSlot, ResetPerTupleExprContext, and TupIsNull.

Referenced by standard_ExecutorRun().

1690 {
1691  TupleTableSlot *slot;
1692  uint64 current_tuple_count;
1693 
1694  /*
1695  * initialize local variables
1696  */
1697  current_tuple_count = 0;
1698 
1699  /*
1700  * Set the direction.
1701  */
1702  estate->es_direction = direction;
1703 
1704  /*
1705  * If the plan might potentially be executed multiple times, we must force
1706  * it to run without parallelism, because we might exit early.
1707  */
1708  if (!execute_once)
1709  use_parallel_mode = false;
1710 
1711  estate->es_use_parallel_mode = use_parallel_mode;
1712  if (use_parallel_mode)
1714 
1715  /*
1716  * Loop until we've processed the proper number of tuples from the plan.
1717  */
1718  for (;;)
1719  {
1720  /* Reset the per-output-tuple exprcontext */
1721  ResetPerTupleExprContext(estate);
1722 
1723  /*
1724  * Execute the plan and obtain a tuple
1725  */
1726  slot = ExecProcNode(planstate);
1727 
1728  /*
1729  * if the tuple is null, then we assume there is nothing more to
1730  * process so we just end the loop...
1731  */
1732  if (TupIsNull(slot))
1733  {
1734  /* Allow nodes to release or shut down resources. */
1735  (void) ExecShutdownNode(planstate);
1736  break;
1737  }
1738 
1739  /*
1740  * If we have a junk filter, then project a new tuple with the junk
1741  * removed.
1742  *
1743  * Store this new "clean" tuple in the junkfilter's resultSlot.
1744  * (Formerly, we stored it back over the "dirty" tuple, which is WRONG
1745  * because that tuple slot has the wrong descriptor.)
1746  */
1747  if (estate->es_junkFilter != NULL)
1748  slot = ExecFilterJunk(estate->es_junkFilter, slot);
1749 
1750  /*
1751  * If we are supposed to send the tuple somewhere, do so. (In
1752  * practice, this is probably always the case at this point.)
1753  */
1754  if (sendTuples)
1755  {
1756  /*
1757  * If we are not able to send the tuple, we assume the destination
1758  * has closed and no more tuples can be sent. If that's the case,
1759  * end the loop.
1760  */
1761  if (!dest->receiveSlot(slot, dest))
1762  break;
1763  }
1764 
1765  /*
1766  * Count tuples processed, if this is a SELECT. (For other operation
1767  * types, the ModifyTable plan node must count the appropriate
1768  * events.)
1769  */
1770  if (operation == CMD_SELECT)
1771  (estate->es_processed)++;
1772 
1773  /*
1774  * check our tuple count.. if we've processed the proper number then
1775  * quit, else loop again and process more tuples. Zero numberTuples
1776  * means no limit.
1777  */
1778  current_tuple_count++;
1779  if (numberTuples && numberTuples == current_tuple_count)
1780  {
1781  /* Allow nodes to release or shut down resources. */
1782  (void) ExecShutdownNode(planstate);
1783  break;
1784  }
1785  }
1786 
1787  if (use_parallel_mode)
1788  ExitParallelMode();
1789 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
JunkFilter * es_junkFilter
Definition: execnodes.h:484
#define ResetPerTupleExprContext(estate)
Definition: executor.h:497
bool ExecShutdownNode(PlanState *node)
Definition: execProcnode.c:746
ScanDirection es_direction
Definition: execnodes.h:477
bool es_use_parallel_mode
Definition: execnodes.h:562
void ExitParallelMode(void)
Definition: xact.c:885
#define TupIsNull(slot)
Definition: tuptable.h:146
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:262
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:232
uint64 es_processed
Definition: execnodes.h:529
void EnterParallelMode(void)
Definition: xact.c:872

◆ ExecutorEnd()

void ExecutorEnd ( QueryDesc queryDesc)

Definition at line 461 of file execMain.c.

References ExecutorEnd_hook, and standard_ExecutorEnd().

Referenced by _SPI_pquery(), EndCopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), ParallelQueryMain(), PersistHoldablePortal(), PortalCleanup(), postquel_end(), ProcessQuery(), and refresh_matview_datafill().

462 {
463  if (ExecutorEnd_hook)
464  (*ExecutorEnd_hook) (queryDesc);
465  else
466  standard_ExecutorEnd(queryDesc);
467 }
void standard_ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:470
ExecutorEnd_hook_type ExecutorEnd_hook
Definition: execMain.c:73

◆ ExecutorFinish()

void ExecutorFinish ( QueryDesc queryDesc)

Definition at line 401 of file execMain.c.

References ExecutorFinish_hook, and standard_ExecutorFinish().

Referenced by _SPI_pquery(), EndCopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), ParallelQueryMain(), PersistHoldablePortal(), PortalCleanup(), postquel_end(), ProcessQuery(), and refresh_matview_datafill().

402 {
404  (*ExecutorFinish_hook) (queryDesc);
405  else
406  standard_ExecutorFinish(queryDesc);
407 }
void standard_ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:410
ExecutorFinish_hook_type ExecutorFinish_hook
Definition: execMain.c:72

◆ ExecutorRewind()

void ExecutorRewind ( QueryDesc queryDesc)

Definition at line 531 of file execMain.c.

References Assert, CMD_SELECT, EState::es_query_cxt, QueryDesc::estate, ExecReScan(), MemoryContextSwitchTo(), QueryDesc::operation, and QueryDesc::planstate.

Referenced by DoPortalRewind(), and PersistHoldablePortal().

532 {
533  EState *estate;
534  MemoryContext oldcontext;
535 
536  /* sanity checks */
537  Assert(queryDesc != NULL);
538 
539  estate = queryDesc->estate;
540 
541  Assert(estate != NULL);
542 
543  /* It's probably not sensible to rescan updating queries */
544  Assert(queryDesc->operation == CMD_SELECT);
545 
546  /*
547  * Switch into per-query memory context
548  */
549  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
550 
551  /*
552  * rescan plan
553  */
554  ExecReScan(queryDesc->planstate);
555 
556  MemoryContextSwitchTo(oldcontext);
557 }
EState * estate
Definition: execdesc.h:48
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:523
PlanState * planstate
Definition: execdesc.h:49
CmdType operation
Definition: execdesc.h:36
#define Assert(condition)
Definition: c.h:699

◆ ExecutorRun()

void ExecutorRun ( QueryDesc queryDesc,
ScanDirection  direction,
uint64  count,
bool  execute_once 
)

Definition at line 299 of file execMain.c.

References ExecutorRun_hook, and standard_ExecutorRun().

Referenced by _SPI_pquery(), CopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), ParallelQueryMain(), PersistHoldablePortal(), PortalRunSelect(), postquel_getnext(), ProcessQuery(), and refresh_matview_datafill().

302 {
303  if (ExecutorRun_hook)
304  (*ExecutorRun_hook) (queryDesc, direction, count, execute_once);
305  else
306  standard_ExecutorRun(queryDesc, direction, count, execute_once);
307 }
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:310
ExecutorRun_hook_type ExecutorRun_hook
Definition: execMain.c:71

◆ ExecutorStart()

void ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 141 of file execMain.c.

References ExecutorStart_hook, and standard_ExecutorStart().

Referenced by _SPI_pquery(), BeginCopy(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), ParallelQueryMain(), PortalStart(), postquel_start(), ProcessQuery(), and refresh_matview_datafill().

142 {
143  if (ExecutorStart_hook)
144  (*ExecutorStart_hook) (queryDesc, eflags);
145  else
146  standard_ExecutorStart(queryDesc, eflags);
147 }
void standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:150
ExecutorStart_hook_type ExecutorStart_hook
Definition: execMain.c:70

◆ ExecWithCheckOptions()

void ExecWithCheckOptions ( WCOKind  kind,
ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate 
)

Definition at line 2099 of file execMain.c.

References bms_union(), convert_tuples_by_name(), do_convert_tuple(), ExprContext::ecxt_scantuple, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecBuildSlotValueDescription(), ExecFetchSlotTuple(), ExecQual(), ExecSetSlotDescriptor(), ExecStoreTuple(), forboth, GetInsertedColumns, GetPerTupleExprContext, gettext_noop, GetUpdatedColumns, InvalidBuffer, WithCheckOption::kind, lfirst, WithCheckOption::polname, RelationGetDescr, RelationGetRelid, WithCheckOption::relname, ResultRelInfo::ri_PartitionRoot, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_WithCheckOptionExprs, ResultRelInfo::ri_WithCheckOptions, WCO_RLS_CONFLICT_CHECK, WCO_RLS_INSERT_CHECK, WCO_RLS_UPDATE_CHECK, and WCO_VIEW_CHECK.

Referenced by ExecInsert(), ExecOnConflictUpdate(), and ExecUpdate().

2101 {
2102  Relation rel = resultRelInfo->ri_RelationDesc;
2103  TupleDesc tupdesc = RelationGetDescr(rel);
2104  ExprContext *econtext;
2105  ListCell *l1,
2106  *l2;
2107 
2108  /*
2109  * We will use the EState's per-tuple context for evaluating constraint
2110  * expressions (creating it if it's not already there).
2111  */
2112  econtext = GetPerTupleExprContext(estate);
2113 
2114  /* Arrange for econtext's scan tuple to be the tuple under test */
2115  econtext->ecxt_scantuple = slot;
2116 
2117  /* Check each of the constraints */
2118  forboth(l1, resultRelInfo->ri_WithCheckOptions,
2119  l2, resultRelInfo->ri_WithCheckOptionExprs)
2120  {
2121  WithCheckOption *wco = (WithCheckOption *) lfirst(l1);
2122  ExprState *wcoExpr = (ExprState *) lfirst(l2);
2123 
2124  /*
2125  * Skip any WCOs which are not the kind we are looking for at this
2126  * time.
2127  */
2128  if (wco->kind != kind)
2129  continue;
2130 
2131  /*
2132  * WITH CHECK OPTION checks are intended to ensure that the new tuple
2133  * is visible (in the case of a view) or that it passes the
2134  * 'with-check' policy (in the case of row security). If the qual
2135  * evaluates to NULL or FALSE, then the new tuple won't be included in
2136  * the view or doesn't pass the 'with-check' policy for the table.
2137  */
2138  if (!ExecQual(wcoExpr, econtext))
2139  {
2140  char *val_desc;
2141  Bitmapset *modifiedCols;
2142  Bitmapset *insertedCols;
2143  Bitmapset *updatedCols;
2144 
2145  switch (wco->kind)
2146  {
2147  /*
2148  * For WITH CHECK OPTIONs coming from views, we might be
2149  * able to provide the details on the row, depending on
2150  * the permissions on the relation (that is, if the user
2151  * could view it directly anyway). For RLS violations, we
2152  * don't include the data since we don't know if the user
2153  * should be able to view the tuple as that depends on the
2154  * USING policy.
2155  */
2156  case WCO_VIEW_CHECK:
2157  /* See the comment in ExecConstraints(). */
2158  if (resultRelInfo->ri_PartitionRoot)
2159  {
2160  HeapTuple tuple = ExecFetchSlotTuple(slot);
2161  TupleDesc old_tupdesc = RelationGetDescr(rel);
2162  TupleConversionMap *map;
2163 
2164  rel = resultRelInfo->ri_PartitionRoot;
2165  tupdesc = RelationGetDescr(rel);
2166  /* a reverse map */
2167  map = convert_tuples_by_name(old_tupdesc, tupdesc,
2168  gettext_noop("could not convert row type"));
2169  if (map != NULL)
2170  {
2171  tuple = do_convert_tuple(tuple, map);
2172  ExecSetSlotDescriptor(slot, tupdesc);
2173  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2174  }
2175  }
2176 
2177  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2178  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2179  modifiedCols = bms_union(insertedCols, updatedCols);
2181  slot,
2182  tupdesc,
2183  modifiedCols,
2184  64);
2185 
2186  ereport(ERROR,
2187  (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),
2188  errmsg("new row violates check option for view \"%s\"",
2189  wco->relname),
2190  val_desc ? errdetail("Failing row contains %s.",
2191  val_desc) : 0));
2192  break;
2193  case WCO_RLS_INSERT_CHECK:
2194  case WCO_RLS_UPDATE_CHECK:
2195  if (wco->polname != NULL)
2196  ereport(ERROR,
2197  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2198  errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
2199  wco->polname, wco->relname)));
2200  else
2201  ereport(ERROR,
2202  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2203  errmsg("new row violates row-level security policy for table \"%s\"",
2204  wco->relname)));
2205  break;
2207  if (wco->polname != NULL)
2208  ereport(ERROR,
2209  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2210  errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2211  wco->polname, wco->relname)));
2212  else
2213  ereport(ERROR,
2214  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2215  errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
2216  wco->relname)));
2217  break;
2218  default:
2219  elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
2220  break;
2221  }
2222  }
2223  }
2224 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:112
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
Relation ri_RelationDesc
Definition: execnodes.h:397
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
#define RelationGetDescr(relation)
Definition: rel.h:433
Relation ri_PartitionRoot
Definition: execnodes.h:460
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:1036
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:360
List * ri_WithCheckOptionExprs
Definition: execnodes.h:433
#define GetPerTupleExprContext(estate)
Definition: executor.h:488
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2246
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
TupleConversionMap * convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc, const char *msg)
Definition: tupconvert.c:210
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:281
List * ri_WithCheckOptions
Definition: execnodes.h:430
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:218
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:661
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define RelationGetRelid(relation)
Definition: rel.h:407
#define GetInsertedColumns(relinfo, estate)
Definition: execMain.c:110

◆ InitPlan()

static void InitPlan ( QueryDesc queryDesc,
int  eflags 
)
static

Definition at line 809 of file execMain.c.

References AccessShareLock, Assert, bms_is_member(), CheckValidRowMarkRel(), CMD_SELECT, ExecRowMark::curCtid, elog, ExecRowMark::ermActive, ExecRowMark::ermExtra, ERROR, EState::es_epqScanDone, EState::es_epqTuple, EState::es_epqTupleSet, EState::es_instrument, EState::es_junkFilter, EState::es_num_result_relations, EState::es_num_root_result_relations, EState::es_plannedstmt, EState::es_range_table, EState::es_result_relation_info, EState::es_result_relations, EState::es_root_result_relations, EState::es_rowMarks, EState::es_subplanstates, EState::es_trig_newtup_slot, EState::es_trig_oldtup_slot, EState::es_trig_tuple_slot, EState::es_tupleTable, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_REWIND, EXEC_FLAG_WITH_NO_DATA, ExecCheckRTPerms(), ExecGetResultType(), ExecInitExtraTupleSlot(), ExecInitJunkFilter(), ExecInitNode(), getrelid, heap_open(), i, InitResultRelInfo(), PlanRowMark::isParent, ItemPointerSetInvalid, JunkFilter::jf_cleanTupType, lappend(), lfirst, lfirst_int, list_length(), list_member_int(), LockRelationOid(), ExecRowMark::markType, PlanRowMark::markType, NIL, PlannedStmt::nonleafResultRelations, QueryDesc::operation, palloc(), PlanState::plan, QueryDesc::plannedstmt, QueryDesc::planstate, PlannedStmt::planTree, ExecRowMark::prti, PlanRowMark::prti, ExecRowMark::relation, ExecRowMark::relid, TargetEntry::resjunk, PlannedStmt::resultRelations, PlannedStmt::rewindPlanIDs, PlannedStmt::rootResultRelations, ROW_MARK_COPY, ROW_MARK_EXCLUSIVE, ROW_MARK_KEYSHARE, ROW_MARK_NOKEYEXCLUSIVE, ROW_MARK_REFERENCE, ROW_MARK_SHARE, RowExclusiveLock, ExecRowMark::rowmarkId, PlanRowMark::rowmarkId, PlannedStmt::rowMarks, RowShareLock, PlannedStmt::rtable, ExecRowMark::rti, PlanRowMark::rti, ExecRowMark::strength, PlanRowMark::strength, PlannedStmt::subplans, Plan::targetlist, tupleDesc::tdhasoid, QueryDesc::tupDesc, ExecRowMark::waitPolicy, and PlanRowMark::waitPolicy.

Referenced by standard_ExecutorStart().

810 {
811  CmdType operation = queryDesc->operation;
812  PlannedStmt *plannedstmt = queryDesc->plannedstmt;
813  Plan *plan = plannedstmt->planTree;
814  List *rangeTable = plannedstmt->rtable;
815  EState *estate = queryDesc->estate;
816  PlanState *planstate;
817  TupleDesc tupType;
818  ListCell *l;
819  int i;
820 
821  /*
822  * Do permissions checks
823  */
824  ExecCheckRTPerms(rangeTable, true);
825 
826  /*
827  * initialize the node's execution state
828  */
829  estate->es_range_table = rangeTable;
830  estate->es_plannedstmt = plannedstmt;
831 
832  /*
833  * initialize result relation stuff, and open/lock the result rels.
834  *
835  * We must do this before initializing the plan tree, else we might try to
836  * do a lock upgrade if a result rel is also a source rel.
837  */
838  if (plannedstmt->resultRelations)
839  {
840  List *resultRelations = plannedstmt->resultRelations;
841  int numResultRelations = list_length(resultRelations);
842  ResultRelInfo *resultRelInfos;
843  ResultRelInfo *resultRelInfo;
844 
845  resultRelInfos = (ResultRelInfo *)
846  palloc(numResultRelations * sizeof(ResultRelInfo));
847  resultRelInfo = resultRelInfos;
848  foreach(l, resultRelations)
849  {
850  Index resultRelationIndex = lfirst_int(l);
851  Oid resultRelationOid;
852  Relation resultRelation;
853 
854  resultRelationOid = getrelid(resultRelationIndex, rangeTable);
855  resultRelation = heap_open(resultRelationOid, RowExclusiveLock);
856 
857  InitResultRelInfo(resultRelInfo,
858  resultRelation,
859  resultRelationIndex,
860  NULL,
861  estate->es_instrument);
862  resultRelInfo++;
863  }
864  estate->es_result_relations = resultRelInfos;
865  estate->es_num_result_relations = numResultRelations;
866  /* es_result_relation_info is NULL except when within ModifyTable */
867  estate->es_result_relation_info = NULL;
868 
869  /*
870  * In the partitioned result relation case, lock the non-leaf result
871  * relations too. A subset of these are the roots of respective
872  * partitioned tables, for which we also allocate ResultRelInfos.
873  */
874  estate->es_root_result_relations = NULL;
875  estate->es_num_root_result_relations = 0;
876  if (plannedstmt->nonleafResultRelations)
877  {
878  int num_roots = list_length(plannedstmt->rootResultRelations);
879 
880  /*
881  * Firstly, build ResultRelInfos for all the partitioned table
882  * roots, because we will need them to fire the statement-level
883  * triggers, if any.
884  */
885  resultRelInfos = (ResultRelInfo *)
886  palloc(num_roots * sizeof(ResultRelInfo));
887  resultRelInfo = resultRelInfos;
888  foreach(l, plannedstmt->rootResultRelations)
889  {
890  Index resultRelIndex = lfirst_int(l);
891  Oid resultRelOid;
892  Relation resultRelDesc;
893 
894  resultRelOid = getrelid(resultRelIndex, rangeTable);
895  resultRelDesc = heap_open(resultRelOid, RowExclusiveLock);
896  InitResultRelInfo(resultRelInfo,
897  resultRelDesc,
898  lfirst_int(l),
899  NULL,
900  estate->es_instrument);
901  resultRelInfo++;
902  }
903 
904  estate->es_root_result_relations = resultRelInfos;
905  estate->es_num_root_result_relations = num_roots;
906 
907  /* Simply lock the rest of them. */
908  foreach(l, plannedstmt->nonleafResultRelations)
909  {
910  Index resultRelIndex = lfirst_int(l);
911 
912  /* We locked the roots above. */
913  if (!list_member_int(plannedstmt->rootResultRelations,
914  resultRelIndex))
915  LockRelationOid(getrelid(resultRelIndex, rangeTable),
917  }
918  }
919  }
920  else
921  {
922  /*
923  * if no result relation, then set state appropriately
924  */
925  estate->es_result_relations = NULL;
926  estate->es_num_result_relations = 0;
927  estate->es_result_relation_info = NULL;
928  estate->es_root_result_relations = NULL;
929  estate->es_num_root_result_relations = 0;
930  }
931 
932  /*
933  * Similarly, we have to lock relations selected FOR [KEY] UPDATE/SHARE
934  * before we initialize the plan tree, else we'd be risking lock upgrades.
935  * While we are at it, build the ExecRowMark list. Any partitioned child
936  * tables are ignored here (because isParent=true) and will be locked by
937  * the first Append or MergeAppend node that references them. (Note that
938  * the RowMarks corresponding to partitioned child tables are present in
939  * the same list as the rest, i.e., plannedstmt->rowMarks.)
940  */
941  estate->es_rowMarks = NIL;
942  foreach(l, plannedstmt->rowMarks)
943  {
944  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
945  Oid relid;
946  Relation relation;
947  ExecRowMark *erm;
948 
949  /* ignore "parent" rowmarks; they are irrelevant at runtime */
950  if (rc->isParent)
951  continue;
952 
953  /* get relation's OID (will produce InvalidOid if subquery) */
954  relid = getrelid(rc->rti, rangeTable);
955 
956  /*
957  * If you change the conditions under which rel locks are acquired
958  * here, be sure to adjust ExecOpenScanRelation to match.
959  */
960  switch (rc->markType)
961  {
962  case ROW_MARK_EXCLUSIVE:
964  case ROW_MARK_SHARE:
965  case ROW_MARK_KEYSHARE:
966  relation = heap_open(relid, RowShareLock);
967  break;
968  case ROW_MARK_REFERENCE:
969  relation = heap_open(relid, AccessShareLock);
970  break;
971  case ROW_MARK_COPY:
972  /* no physical table access is required */
973  relation = NULL;
974  break;
975  default:
976  elog(ERROR, "unrecognized markType: %d", rc->markType);
977  relation = NULL; /* keep compiler quiet */
978  break;
979  }
980 
981  /* Check that relation is a legal target for marking */
982  if (relation)
983  CheckValidRowMarkRel(relation, rc->markType);
984 
985  erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
986  erm->relation = relation;
987  erm->relid = relid;
988  erm->rti = rc->rti;
989  erm->prti = rc->prti;
990  erm->rowmarkId = rc->rowmarkId;
991  erm->markType = rc->markType;
992  erm->strength = rc->strength;
993  erm->waitPolicy = rc->waitPolicy;
994  erm->ermActive = false;
996  erm->ermExtra = NULL;
997  estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
998  }
999 
1000  /*
1001  * Initialize the executor's tuple table to empty.
1002  */
1003  estate->es_tupleTable = NIL;
1004  estate->es_trig_tuple_slot = NULL;
1005  estate->es_trig_oldtup_slot = NULL;
1006  estate->es_trig_newtup_slot = NULL;
1007 
1008  /* mark EvalPlanQual not active */
1009  estate->es_epqTuple = NULL;
1010  estate->es_epqTupleSet = NULL;
1011  estate->es_epqScanDone = NULL;
1012 
1013  /*
1014  * Initialize private state information for each SubPlan. We must do this
1015  * before running ExecInitNode on the main query tree, since
1016  * ExecInitSubPlan expects to be able to find these entries.
1017  */
1018  Assert(estate->es_subplanstates == NIL);
1019  i = 1; /* subplan indices count from 1 */
1020  foreach(l, plannedstmt->subplans)
1021  {
1022  Plan *subplan = (Plan *) lfirst(l);
1023  PlanState *subplanstate;
1024  int sp_eflags;
1025 
1026  /*
1027  * A subplan will never need to do BACKWARD scan nor MARK/RESTORE. If
1028  * it is a parameterless subplan (not initplan), we suggest that it be
1029  * prepared to handle REWIND efficiently; otherwise there is no need.
1030  */
1031  sp_eflags = eflags
1033  if (bms_is_member(i, plannedstmt->rewindPlanIDs))
1034  sp_eflags |= EXEC_FLAG_REWIND;
1035 
1036  subplanstate = ExecInitNode(subplan, estate, sp_eflags);
1037 
1038  estate->es_subplanstates = lappend(estate->es_subplanstates,
1039  subplanstate);
1040 
1041  i++;
1042  }
1043 
1044  /*
1045  * Initialize the private state information for all the nodes in the query
1046  * tree. This opens files, allocates storage and leaves us ready to start
1047  * processing tuples.
1048  */
1049  planstate = ExecInitNode(plan, estate, eflags);
1050 
1051  /*
1052  * Get the tuple descriptor describing the type of tuples to return.
1053  */
1054  tupType = ExecGetResultType(planstate);
1055 
1056  /*
1057  * Initialize the junk filter if needed. SELECT queries need a filter if
1058  * there are any junk attrs in the top-level tlist.
1059  */
1060  if (operation == CMD_SELECT)
1061  {
1062  bool junk_filter_needed = false;
1063  ListCell *tlist;
1064 
1065  foreach(tlist, plan->targetlist)
1066  {
1067  TargetEntry *tle = (TargetEntry *) lfirst(tlist);
1068 
1069  if (tle->resjunk)
1070  {
1071  junk_filter_needed = true;
1072  break;
1073  }
1074  }
1075 
1076  if (junk_filter_needed)
1077  {
1078  JunkFilter *j;
1079 
1080  j = ExecInitJunkFilter(planstate->plan->targetlist,
1081  tupType->tdhasoid,
1082  ExecInitExtraTupleSlot(estate, NULL));
1083  estate->es_junkFilter = j;
1084 
1085  /* Want to return the cleaned tuple type */
1086  tupType = j->jf_cleanTupType;
1087  }
1088  }
1089 
1090  queryDesc->tupDesc = tupType;
1091  queryDesc->planstate = planstate;
1092 }
#define NIL
Definition: pg_list.h:69
HeapTuple * es_epqTuple
Definition: execnodes.h:558
JunkFilter * es_junkFilter
Definition: execnodes.h:484
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1305
RowMarkType markType
Definition: plannodes.h:1041
EState * estate
Definition: execdesc.h:48
bool tdhasoid
Definition: tupdesc.h:85
List * nonleafResultRelations
Definition: plannodes.h:75
TupleTableSlot * es_trig_newtup_slot
Definition: execnodes.h:514
Relation relation
Definition: execnodes.h:596
#define AccessShareLock
Definition: lockdefs.h:36
PlannedStmt * es_plannedstmt
Definition: execnodes.h:481
bool ermActive
Definition: execnodes.h:604
Index prti
Definition: plannodes.h:1039
LockWaitPolicy waitPolicy
Definition: execnodes.h:603
#define EXEC_FLAG_WITH_NO_DATA
Definition: executor.h:65
LockClauseStrength strength
Definition: execnodes.h:602
List * es_range_table
Definition: execnodes.h:480
unsigned int Oid
Definition: postgres_ext.h:31
Index rowmarkId
Definition: plannodes.h:1040
LockWaitPolicy waitPolicy
Definition: plannodes.h:1044
static void CheckValidRowMarkRel(Relation rel, RowMarkType markType)
Definition: execMain.c:1240
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
Definition: execTuples.c:931
struct Plan * planTree
Definition: plannodes.h:64
ItemPointerData curCtid
Definition: execnodes.h:605
bool resjunk
Definition: primnodes.h:1382
#define ERROR
Definition: elog.h:43
PlanState * planstate
Definition: execdesc.h:49
#define lfirst_int(lc)
Definition: pg_list.h:107
bool list_member_int(const List *list, int datum)
Definition: list.c:485
Index rti
Definition: execnodes.h:598
void * ermExtra
Definition: execnodes.h:606
TupleDesc jf_cleanTupType
Definition: execnodes.h:362
ResultRelInfo * es_result_relations
Definition: execnodes.h:490
#define RowExclusiveLock
Definition: lockdefs.h:38
Index prti
Definition: execnodes.h:599
JunkFilter * ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
Definition: execJunk.c:61
List * rootResultRelations
Definition: plannodes.h:82
TupleTableSlot * es_trig_oldtup_slot
Definition: execnodes.h:513
int es_instrument
Definition: execnodes.h:533
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:512
#define EXEC_FLAG_REWIND
Definition: executor.h:59
Index rowmarkId
Definition: execnodes.h:600
List * lappend(List *list, void *datum)
Definition: list.c:128
int es_num_root_result_relations
Definition: execnodes.h:502
TupleDesc tupDesc
Definition: execdesc.h:47
CmdType operation
Definition: execdesc.h:36
List * es_tupleTable
Definition: execnodes.h:525
#define RowShareLock
Definition: lockdefs.h:37
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
int es_num_result_relations
Definition: execnodes.h:491
unsigned int Index
Definition: c.h:442
List * rowMarks
Definition: plannodes.h:89
Plan * plan
Definition: execnodes.h:912
List * subplans
Definition: plannodes.h:84
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * rewindPlanIDs
Definition: plannodes.h:87
RowMarkType markType
Definition: execnodes.h:601
LockClauseStrength strength
Definition: plannodes.h:1043
static int list_length(const List *l)
Definition: pg_list.h:89
bool * es_epqTupleSet
Definition: execnodes.h:559
List * es_subplanstates
Definition: execnodes.h:538
List * es_rowMarks
Definition: execnodes.h:527
List * rtable
Definition: plannodes.h:66
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:438
List * targetlist
Definition: plannodes.h:147
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
void * palloc(Size size)
Definition: mcxt.c:924
#define getrelid(rangeindex, rangetable)
Definition: parsetree.h:41
List * resultRelations
Definition: plannodes.h:69
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:501
int i
bool * es_epqScanDone
Definition: execnodes.h:560
bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
Definition: execMain.c:574
bool isParent
Definition: plannodes.h:1045
#define elog
Definition: elog.h:219
PlannedStmt * plannedstmt
Definition: execdesc.h:37
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
CmdType
Definition: nodes.h:656
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:492

◆ InitResultRelInfo()

void InitResultRelInfo ( ResultRelInfo resultRelInfo,
Relation  resultRelationDesc,
Index  resultRelationIndex,
Relation  partition_root,
int  instrument_options 
)

Definition at line 1305 of file execMain.c.

References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), MemSet, NIL, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, RelationGetPartitionQual(), ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_onConflict, ResultRelInfo::ri_onConflictArbiterIndexes, ResultRelInfo::ri_PartitionCheck, ResultRelInfo::ri_PartitionReadyForRouting, ResultRelInfo::ri_PartitionRoot, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RangeTableIndex, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, ResultRelInfo::ri_TrigWhenExprs, ResultRelInfo::ri_usesFdwDirectModify, T_ResultRelInfo, RelationData::trigdesc, and ResultRelInfo::type.

Referenced by CopyFrom(), create_estate_for_relation(), ExecGetTriggerResultRel(), ExecInitPartitionInfo(), ExecuteTruncateGuts(), and InitPlan().

1310 {
1311  List *partition_check = NIL;
1312 
1313  MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1314  resultRelInfo->type = T_ResultRelInfo;
1315  resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1316  resultRelInfo->ri_RelationDesc = resultRelationDesc;
1317  resultRelInfo->ri_NumIndices = 0;
1318  resultRelInfo->ri_IndexRelationDescs = NULL;
1319  resultRelInfo->ri_IndexRelationInfo = NULL;
1320  /* make a copy so as not to depend on relcache info not changing... */
1321  resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1322  if (resultRelInfo->ri_TrigDesc)
1323  {
1324  int n = resultRelInfo->ri_TrigDesc->numtriggers;
1325 
1326  resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1327  palloc0(n * sizeof(FmgrInfo));
1328  resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1329  palloc0(n * sizeof(ExprState *));
1330  if (instrument_options)
1331  resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options);
1332  }
1333  else
1334  {
1335  resultRelInfo->ri_TrigFunctions = NULL;
1336  resultRelInfo->ri_TrigWhenExprs = NULL;
1337  resultRelInfo->ri_TrigInstrument = NULL;
1338  }
1339  if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1340  resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
1341  else
1342  resultRelInfo->ri_FdwRoutine = NULL;
1343 
1344  /* The following fields are set later if needed */
1345  resultRelInfo->ri_FdwState = NULL;
1346  resultRelInfo->ri_usesFdwDirectModify = false;
1347  resultRelInfo->ri_ConstraintExprs = NULL;
1348  resultRelInfo->ri_junkFilter = NULL;
1349  resultRelInfo->ri_projectReturning = NULL;
1350  resultRelInfo->ri_onConflictArbiterIndexes = NIL;
1351  resultRelInfo->ri_onConflict = NULL;
1352 
1353  /*
1354  * Partition constraint, which also includes the partition constraint of
1355  * all the ancestors that are partitions. Note that it will be checked
1356  * even in the case of tuple-routing where this table is the target leaf
1357  * partition, if there any BR triggers defined on the table. Although
1358  * tuple-routing implicitly preserves the partition constraint of the
1359  * target partition for a given row, the BR triggers may change the row
1360  * such that the constraint is no longer satisfied, which we must fail for
1361  * by checking it explicitly.
1362  *
1363  * If this is a partitioned table, the partition constraint (if any) of a
1364  * given row will be checked just before performing tuple-routing.
1365  */
1366  partition_check = RelationGetPartitionQual(resultRelationDesc);
1367 
1368  resultRelInfo->ri_PartitionCheck = partition_check;
1369  resultRelInfo->ri_PartitionRoot = partition_root;
1370  resultRelInfo->ri_PartitionReadyForRouting = false;
1371 }
int ri_NumIndices
Definition: execnodes.h:400
#define NIL
Definition: pg_list.h:69
JunkFilter * ri_junkFilter
Definition: execnodes.h:439
Definition: fmgr.h:56
Relation ri_RelationDesc
Definition: execnodes.h:397
Relation ri_PartitionRoot
Definition: execnodes.h:460
bool ri_PartitionReadyForRouting
Definition: execnodes.h:463
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:418
Instrumentation * InstrAlloc(int n, int instrument_options)
Definition: instrument.c:30
#define MemSet(start, val, len)
Definition: c.h:908
Form_pg_class rd_rel
Definition: rel.h:84
Index ri_RangeTableIndex
Definition: execnodes.h:394
NodeTag type
Definition: execnodes.h:391
TriggerDesc * trigdesc
Definition: rel.h:90
bool ri_usesFdwDirectModify
Definition: execnodes.h:427
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:415
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:445
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:421
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:436
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:409
int numtriggers
Definition: reltrigger.h:49
OnConflictSetState * ri_onConflict
Definition: execnodes.h:451
void * palloc0(Size size)
Definition: mcxt.c:955
List * ri_PartitionCheck
Definition: execnodes.h:454
void * ri_FdwState
Definition: execnodes.h:424
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:2138
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:406
List * RelationGetPartitionQual(Relation rel)
Definition: partcache.c:799
Definition: pg_list.h:45
List * ri_onConflictArbiterIndexes
Definition: execnodes.h:448
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:403
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:412

◆ standard_ExecutorEnd()

void standard_ExecutorEnd ( QueryDesc queryDesc)

Definition at line 470 of file execMain.c.

References Assert, EState::es_crosscheck_snapshot, EState::es_finished, EState::es_jit, EState::es_query_cxt, EState::es_snapshot, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecEndPlan(), FreeExecutorState(), jit_release_context(), MemoryContextSwitchTo(), QueryDesc::planstate, QueryDesc::totaltime, QueryDesc::tupDesc, and UnregisterSnapshot().

Referenced by ExecutorEnd(), explain_ExecutorEnd(), and pgss_ExecutorEnd().

471 {
472  EState *estate;
473  MemoryContext oldcontext;
474 
475  /* sanity checks */
476  Assert(queryDesc != NULL);
477 
478  estate = queryDesc->estate;
479 
480  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  Assert(estate->es_finished ||
489 
490  /*
491  * Switch into per-query memory context to run ExecEndPlan
492  */
493  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
494 
495  ExecEndPlan(queryDesc->planstate, estate);
496 
497  /* do away with our snapshots */
500 
501  /* release JIT context, if allocated */
502  if (estate->es_jit)
503  jit_release_context(estate->es_jit);
504 
505  /*
506  * Must switch out of context before destroying it
507  */
508  MemoryContextSwitchTo(oldcontext);
509 
510  /*
511  * Release EState and per-query memory context. This should release
512  * everything the executor has allocated.
513  */
514  FreeExecutorState(estate);
515 
516  /* Reset queryDesc fields that no longer point to anything */
517  queryDesc->tupDesc = NULL;
518  queryDesc->estate = NULL;
519  queryDesc->planstate = NULL;
520  queryDesc->totaltime = NULL;
521 }
EState * estate
Definition: execdesc.h:48
struct JitContext * es_jit
Definition: execnodes.h:573
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:479
Snapshot es_snapshot
Definition: execnodes.h:478
void FreeExecutorState(EState *estate)
Definition: execUtils.c:188
MemoryContext es_query_cxt
Definition: execnodes.h:523
PlanState * planstate
Definition: execdesc.h:49
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:905
TupleDesc tupDesc
Definition: execdesc.h:47
bool es_finished
Definition: execnodes.h:534
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:699
static void ExecEndPlan(PlanState *planstate, EState *estate)
Definition: execMain.c:1603
void jit_release_context(JitContext *context)
Definition: jit.c:141
int es_top_eflags
Definition: execnodes.h:532
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58

◆ standard_ExecutorFinish()

void standard_ExecutorFinish ( QueryDesc queryDesc)

Definition at line 410 of file execMain.c.

References AfterTriggerEndQuery(), Assert, EState::es_finished, EState::es_query_cxt, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_SKIP_TRIGGERS, ExecPostprocessPlan(), InstrStartNode(), InstrStopNode(), MemoryContextSwitchTo(), and QueryDesc::totaltime.

Referenced by ExecutorFinish(), explain_ExecutorFinish(), and pgss_ExecutorFinish().

411 {
412  EState *estate;
413  MemoryContext oldcontext;
414 
415  /* sanity checks */
416  Assert(queryDesc != NULL);
417 
418  estate = queryDesc->estate;
419 
420  Assert(estate != NULL);
422 
423  /* This should be run once and only once per Executor instance */
424  Assert(!estate->es_finished);
425 
426  /* Switch into per-query memory context */
427  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
428 
429  /* Allow instrumentation of Executor overall runtime */
430  if (queryDesc->totaltime)
431  InstrStartNode(queryDesc->totaltime);
432 
433  /* Run ModifyTable nodes to completion */
434  ExecPostprocessPlan(estate);
435 
436  /* Execute queued AFTER triggers, unless told not to */
437  if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
438  AfterTriggerEndQuery(estate);
439 
440  if (queryDesc->totaltime)
441  InstrStopNode(queryDesc->totaltime, 0);
442 
443  MemoryContextSwitchTo(oldcontext);
444 
445  estate->es_finished = true;
446 }
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:80
static void ExecPostprocessPlan(EState *estate)
Definition: execMain.c:1557
EState * estate
Definition: execdesc.h:48
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:523
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:63
bool es_finished
Definition: execnodes.h:534
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:699
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:62
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4786
int es_top_eflags
Definition: execnodes.h:532
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58

◆ standard_ExecutorRun()

void standard_ExecutorRun ( QueryDesc queryDesc,
ScanDirection  direction,
uint64  count,
bool  execute_once 
)

Definition at line 310 of file execMain.c.

References QueryDesc::already_executed, Assert, CMD_SELECT, QueryDesc::dest, generate_unaccent_rules::dest, elog, ERROR, EState::es_lastoid, EState::es_processed, EState::es_query_cxt, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecutePlan(), PlannedStmt::hasReturning, InstrStartNode(), InstrStopNode(), InvalidOid, MemoryContextSwitchTo(), QueryDesc::operation, PlannedStmt::parallelModeNeeded, QueryDesc::plannedstmt, QueryDesc::planstate, _DestReceiver::rShutdown, _DestReceiver::rStartup, ScanDirectionIsNoMovement, QueryDesc::totaltime, and QueryDesc::tupDesc.

Referenced by ExecutorRun(), explain_ExecutorRun(), and pgss_ExecutorRun().

312 {
313  EState *estate;
314  CmdType operation;
316  bool sendTuples;
317  MemoryContext oldcontext;
318 
319  /* sanity checks */
320  Assert(queryDesc != NULL);
321 
322  estate = queryDesc->estate;
323 
324  Assert(estate != NULL);
326 
327  /*
328  * Switch into per-query memory context
329  */
330  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
331 
332  /* Allow instrumentation of Executor overall runtime */
333  if (queryDesc->totaltime)
334  InstrStartNode(queryDesc->totaltime);
335 
336  /*
337  * extract information from the query descriptor and the query feature.
338  */
339  operation = queryDesc->operation;
340  dest = queryDesc->dest;
341 
342  /*
343  * startup tuple receiver, if we will be emitting tuples
344  */
345  estate->es_processed = 0;
346  estate->es_lastoid = InvalidOid;
347 
348  sendTuples = (operation == CMD_SELECT ||
349  queryDesc->plannedstmt->hasReturning);
350 
351  if (sendTuples)
352  dest->rStartup(dest, operation, queryDesc->tupDesc);
353 
354  /*
355  * run plan
356  */
357  if (!ScanDirectionIsNoMovement(direction))
358  {
359  if (execute_once && queryDesc->already_executed)
360  elog(ERROR, "can't re-execute query flagged for single execution");
361  queryDesc->already_executed = true;
362 
363  ExecutePlan(estate,
364  queryDesc->planstate,
365  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  if (sendTuples)
378  dest->rShutdown(dest);
379 
380  if (queryDesc->totaltime)
381  InstrStopNode(queryDesc->totaltime, estate->es_processed);
382 
383  MemoryContextSwitchTo(oldcontext);
384 }
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:80
EState * estate
Definition: execdesc.h:48
Oid es_lastoid
Definition: execnodes.h:530
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:48
MemoryContext es_query_cxt
Definition: execnodes.h:523
#define ERROR
Definition: elog.h:43
PlanState * planstate
Definition: execdesc.h:49
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:63
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
bool hasReturning
Definition: plannodes.h:50
TupleDesc tupDesc
Definition: execdesc.h:47
CmdType operation
Definition: execdesc.h:36
bool already_executed
Definition: execdesc.h:52
#define InvalidOid
Definition: postgres_ext.h:36
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:699
uint64 es_processed
Definition: execnodes.h:529
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
DestReceiver * dest
Definition: execdesc.h:41
int es_top_eflags
Definition: execnodes.h:532
bool parallelModeNeeded
Definition: plannodes.h:60
#define elog
Definition: elog.h:219
PlannedStmt * plannedstmt
Definition: execdesc.h:37
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
CmdType
Definition: nodes.h:656
static void ExecutePlan(EState *estate, PlanState *planstate, bool use_parallel_mode, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, DestReceiver *dest, bool execute_once)
Definition: execMain.c:1681

◆ standard_ExecutorStart()

void standard_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 150 of file execMain.c.

References AfterTriggerBeginQuery(), Assert, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, CreateExecutorState(), QueryDesc::crosscheck_snapshot, elog, ERROR, EState::es_crosscheck_snapshot, EState::es_instrument, EState::es_jit_flags, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_query_cxt, EState::es_queryEnv, EState::es_snapshot, EState::es_sourceText, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_SKIP_TRIGGERS, ExecCheckXactReadOnly(), GetCurrentCommandId(), PlannedStmt::hasModifyingCTE, InitPlan(), QueryDesc::instrument_options, IsInParallelMode(), PlannedStmt::jitFlags, list_length(), MemoryContextSwitchTo(), NIL, QueryDesc::operation, palloc0(), PlannedStmt::paramExecTypes, QueryDesc::params, QueryDesc::plannedstmt, QueryDesc::queryEnv, RegisterSnapshot(), PlannedStmt::rowMarks, QueryDesc::snapshot, QueryDesc::sourceText, and XactReadOnly.

Referenced by ExecutorStart(), explain_ExecutorStart(), and pgss_ExecutorStart().

151 {
152  EState *estate;
153  MemoryContext oldcontext;
154 
155  /* sanity checks: queryDesc must not be started already */
156  Assert(queryDesc != NULL);
157  Assert(queryDesc->estate == NULL);
158 
159  /*
160  * If the transaction is read-only, we need to check if any writes are
161  * planned to non-temporary tables. EXPLAIN is considered read-only.
162  *
163  * Don't allow writes in parallel mode. Supporting UPDATE and DELETE
164  * would require (a) storing the combocid hash in shared memory, rather
165  * than synchronizing it just once at the start of parallelism, and (b) an
166  * alternative to heap_update()'s reliance on xmax for mutual exclusion.
167  * INSERT may have no such troubles, but we forbid it to simplify the
168  * checks.
169  *
170  * We have lower-level defenses in CommandCounterIncrement and elsewhere
171  * against performing unsafe operations in parallel mode, but this gives a
172  * more user-friendly error message.
173  */
174  if ((XactReadOnly || IsInParallelMode()) &&
175  !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
177 
178  /*
179  * Build EState, switch into per-query memory context for startup.
180  */
181  estate = CreateExecutorState();
182  queryDesc->estate = estate;
183 
184  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
185 
186  /*
187  * Fill in external parameters, if any, from queryDesc; and allocate
188  * workspace for internal parameters
189  */
190  estate->es_param_list_info = queryDesc->params;
191 
192  if (queryDesc->plannedstmt->paramExecTypes != NIL)
193  {
194  int nParamExec;
195 
196  nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes);
197  estate->es_param_exec_vals = (ParamExecData *)
198  palloc0(nParamExec * sizeof(ParamExecData));
199  }
200 
201  estate->es_sourceText = queryDesc->sourceText;
202 
203  /*
204  * Fill in the query environment, if any, from queryDesc.
205  */
206  estate->es_queryEnv = queryDesc->queryEnv;
207 
208  /*
209  * If non-read-only query, set the command ID to mark output tuples with
210  */
211  switch (queryDesc->operation)
212  {
213  case CMD_SELECT:
214 
215  /*
216  * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark
217  * tuples
218  */
219  if (queryDesc->plannedstmt->rowMarks != NIL ||
220  queryDesc->plannedstmt->hasModifyingCTE)
221  estate->es_output_cid = GetCurrentCommandId(true);
222 
223  /*
224  * A SELECT without modifying CTEs can't possibly queue triggers,
225  * so force skip-triggers mode. This is just a marginal efficiency
226  * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't
227  * all that expensive, but we might as well do it.
228  */
229  if (!queryDesc->plannedstmt->hasModifyingCTE)
230  eflags |= EXEC_FLAG_SKIP_TRIGGERS;
231  break;
232 
233  case CMD_INSERT:
234  case CMD_DELETE:
235  case CMD_UPDATE:
236  estate->es_output_cid = GetCurrentCommandId(true);
237  break;
238 
239  default:
240  elog(ERROR, "unrecognized operation code: %d",
241  (int) queryDesc->operation);
242  break;
243  }
244 
245  /*
246  * Copy other important information into the EState
247  */
248  estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot);
250  estate->es_top_eflags = eflags;
251  estate->es_instrument = queryDesc->instrument_options;
252  estate->es_jit_flags = queryDesc->plannedstmt->jitFlags;
253 
254  /*
255  * Set up an AFTER-trigger statement context, unless told not to, or
256  * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called).
257  */
258  if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY)))
260 
261  /*
262  * Initialize the plan state tree
263  */
264  InitPlan(queryDesc, eflags);
265 
266  MemoryContextSwitchTo(oldcontext);
267 }
List * paramExecTypes
Definition: plannodes.h:95
#define NIL
Definition: pg_list.h:69
EState * estate
Definition: execdesc.h:48
CommandId es_output_cid
Definition: execnodes.h:487
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:479
Snapshot es_snapshot
Definition: execnodes.h:478
Snapshot snapshot
Definition: execdesc.h:39
int instrument_options
Definition: execdesc.h:44
const char * es_sourceText
Definition: execnodes.h:482
ParamExecData * es_param_exec_vals
Definition: execnodes.h:518
QueryEnvironment * queryEnv
Definition: execdesc.h:43
MemoryContext es_query_cxt
Definition: execnodes.h:523
bool IsInParallelMode(void)
Definition: xact.c:905
#define ERROR
Definition: elog.h:43
int es_jit_flags
Definition: execnodes.h:572
ParamListInfo params
Definition: execdesc.h:42
int jitFlags
Definition: plannodes.h:62
int es_instrument
Definition: execnodes.h:533
EState * CreateExecutorState(void)
Definition: execUtils.c:80
QueryEnvironment * es_queryEnv
Definition: execnodes.h:520
CmdType operation
Definition: execdesc.h:36
static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
Definition: execMain.c:772
void * palloc0(Size size)
Definition: mcxt.c:955
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
List * rowMarks
Definition: plannodes.h:89
bool XactReadOnly
Definition: xact.c:76
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4766
#define Assert(condition)
Definition: c.h:699
bool hasModifyingCTE
Definition: plannodes.h:52
static int list_length(const List *l)
Definition: pg_list.h:89
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:62
const char * sourceText
Definition: execdesc.h:38
int es_top_eflags
Definition: execnodes.h:532
ParamListInfo es_param_list_info
Definition: execnodes.h:517
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:679
#define elog
Definition: elog.h:219
PlannedStmt * plannedstmt
Definition: execdesc.h:37
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
static void InitPlan(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:809

Variable Documentation

◆ ExecutorCheckPerms_hook

ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL

Definition at line 76 of file execMain.c.

Referenced by _PG_init(), and ExecCheckRTPerms().

◆ ExecutorEnd_hook

ExecutorEnd_hook_type ExecutorEnd_hook = NULL

Definition at line 73 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorEnd().

◆ ExecutorFinish_hook

ExecutorFinish_hook_type ExecutorFinish_hook = NULL

Definition at line 72 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorFinish().

◆ ExecutorRun_hook

ExecutorRun_hook_type ExecutorRun_hook = NULL

Definition at line 71 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorRun().

◆ ExecutorStart_hook

ExecutorStart_hook_type ExecutorStart_hook = NULL

Definition at line 70 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorStart().