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/partition.h"
#include "catalog/pg_publication.h"
#include "commands/matview.h"
#include "commands/trigger.h"
#include "executor/execdebug.h"
#include "foreign/fdwapi.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/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)
 
void ExecPartitionCheckEmitError (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
void ExecConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool check_partition_constraint)
 
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 109 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 1098 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, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_PartitionRoot, ResultRelInfo::ri_RelationDesc, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, and RelationData::trigdesc.

Referenced by ExecInitModifyTable(), and ExecSetupPartitionTupleRouting().

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

◆ CheckValidRowMarkRel()

static void CheckValidRowMarkRel ( Relation  rel,
RowMarkType  markType 
)
static

Definition at line 1241 of file execMain.c.

References ereport, errcode(), errmsg(), ERROR, GetFdwRoutineForRelation(), RelationData::rd_rel, FdwRoutine::RefetchForeignRow, RelationGetRelationName, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, and ROW_MARK_REFERENCE.

Referenced by InitPlan().

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

◆ EvalPlanQual()

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

Definition at line 2496 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate,
EState parentestate 
)

Definition at line 3033 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().

3034 {
3035  EState *estate = epqstate->estate;
3036 
3037  if (estate == NULL)
3038  {
3039  /* First time through, so create a child EState */
3040  EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
3041  }
3042  else
3043  {
3044  /*
3045  * We already have a suitable child EPQ tree, so just reset it.
3046  */
3047  int rtsize = list_length(parentestate->es_range_table);
3048  PlanState *planstate = epqstate->planstate;
3049 
3050  MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
3051 
3052  /* Recopy current values of parent parameters */
3053  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
3054  {
3055  int i;
3056 
3057  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
3058 
3059  while (--i >= 0)
3060  {
3061  /* copy value if any, but not execPlan link */
3062  estate->es_param_exec_vals[i].value =
3063  parentestate->es_param_exec_vals[i].value;
3064  estate->es_param_exec_vals[i].isnull =
3065  parentestate->es_param_exec_vals[i].isnull;
3066  }
3067  }
3068 
3069  /*
3070  * Mark child plan tree as needing rescan at all scan nodes. The
3071  * first ExecProcNode will take care of actually doing the rescan.
3072  */
3073  planstate->chgParam = bms_add_member(planstate->chgParam,
3074  epqstate->epqParam);
3075  }
3076 }
List * paramExecTypes
Definition: plannodes.h:92
#define NIL
Definition: pg_list.h:69
PlannedStmt * es_plannedstmt
Definition: execnodes.h:446
#define MemSet(start, val, len)
Definition: c.h:897
List * es_range_table
Definition: execnodes.h:445
PlanState * planstate
Definition: execnodes.h:936
ParamExecData * es_param_exec_vals
Definition: execnodes.h:483
bool isnull
Definition: params.h:149
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
Definition: execMain.c:3085
Bitmapset * chgParam
Definition: execnodes.h:896
Plan * plan
Definition: execnodes.h:938
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:742
int i
bool * es_epqScanDone
Definition: execnodes.h:525
Datum value
Definition: params.h:148
int epqParam
Definition: execnodes.h:940
EState * estate
Definition: execnodes.h:935

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 3226 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().

3227 {
3228  EState *estate = epqstate->estate;
3229  MemoryContext oldcontext;
3230  ListCell *l;
3231 
3232  if (estate == NULL)
3233  return; /* idle, so nothing to do */
3234 
3235  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3236 
3237  ExecEndNode(epqstate->planstate);
3238 
3239  foreach(l, estate->es_subplanstates)
3240  {
3241  PlanState *subplanstate = (PlanState *) lfirst(l);
3242 
3243  ExecEndNode(subplanstate);
3244  }
3245 
3246  /* throw away the per-estate tuple table */
3247  ExecResetTupleTable(estate->es_tupleTable, false);
3248 
3249  /* close any trigger target relations attached to this EState */
3250  ExecCleanUpTriggerState(estate);
3251 
3252  MemoryContextSwitchTo(oldcontext);
3253 
3254  FreeExecutorState(estate);
3255 
3256  /* Mark EPQState idle */
3257  epqstate->estate = NULL;
3258  epqstate->planstate = NULL;
3259  epqstate->origslot = NULL;
3260 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:936
void FreeExecutorState(EState *estate)
Definition: execUtils.c:185
MemoryContext es_query_cxt
Definition: execnodes.h:488
TupleTableSlot * origslot
Definition: execnodes.h:937
List * es_tupleTable
Definition: execnodes.h:490
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:186
#define lfirst(lc)
Definition: pg_list.h:106
List * es_subplanstates
Definition: execnodes.h:503
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1469
EState * estate
Definition: execnodes.h:935

◆ EvalPlanQualFetch()

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

Definition at line 2583 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, HeapTupleHeaderIsSpeculative, HeapTupleInvisible, HeapTupleMayBeUpdated, HeapTupleSelfUpdated, HeapTupleUpdated, HeapTupleWouldBlock, InitDirtySnapshot, IsolationUsesXactSnapshot, ItemPointerEquals(), 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().

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

2883 {
2884  ListCell *l;
2885 
2886  Assert(epqstate->origslot != NULL);
2887 
2888  foreach(l, epqstate->arowMarks)
2889  {
2890  ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
2891  ExecRowMark *erm = aerm->rowmark;
2892  Datum datum;
2893  bool isNull;
2894  HeapTupleData tuple;
2895 
2897  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2898 
2899  /* clear any leftover test tuple for this rel */
2900  EvalPlanQualSetTuple(epqstate, erm->rti, NULL);
2901 
2902  /* if child rel, must check whether it produced this row */
2903  if (erm->rti != erm->prti)
2904  {
2905  Oid tableoid;
2906 
2907  datum = ExecGetJunkAttribute(epqstate->origslot,
2908  aerm->toidAttNo,
2909  &isNull);
2910  /* non-locked rels could be on the inside of outer joins */
2911  if (isNull)
2912  continue;
2913  tableoid = DatumGetObjectId(datum);
2914 
2915  Assert(OidIsValid(erm->relid));
2916  if (tableoid != erm->relid)
2917  {
2918  /* this child is inactive right now */
2919  continue;
2920  }
2921  }
2922 
2923  if (erm->markType == ROW_MARK_REFERENCE)
2924  {
2925  HeapTuple copyTuple;
2926 
2927  Assert(erm->relation != NULL);
2928 
2929  /* fetch the tuple's ctid */
2930  datum = ExecGetJunkAttribute(epqstate->origslot,
2931  aerm->ctidAttNo,
2932  &isNull);
2933  /* non-locked rels could be on the inside of outer joins */
2934  if (isNull)
2935  continue;
2936 
2937  /* fetch requests on foreign tables must be passed to their FDW */
2938  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2939  {
2940  FdwRoutine *fdwroutine;
2941  bool updated = false;
2942 
2943  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2944  /* this should have been checked already, but let's be safe */
2945  if (fdwroutine->RefetchForeignRow == NULL)
2946  ereport(ERROR,
2947  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2948  errmsg("cannot lock rows in foreign table \"%s\"",
2950  copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate,
2951  erm,
2952  datum,
2953  &updated);
2954  if (copyTuple == NULL)
2955  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2956 
2957  /*
2958  * Ideally we'd insist on updated == false here, but that
2959  * assumes that FDWs can track that exactly, which they might
2960  * not be able to. So just ignore the flag.
2961  */
2962  }
2963  else
2964  {
2965  /* ordinary table, fetch the tuple */
2966  Buffer buffer;
2967 
2968  tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
2969  if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
2970  false, NULL))
2971  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2972 
2973  /* successful, copy tuple */
2974  copyTuple = heap_copytuple(&tuple);
2975  ReleaseBuffer(buffer);
2976  }
2977 
2978  /* store tuple */
2979  EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
2980  }
2981  else
2982  {
2983  HeapTupleHeader td;
2984 
2985  Assert(erm->markType == ROW_MARK_COPY);
2986 
2987  /* fetch the whole-row Var for the relation */
2988  datum = ExecGetJunkAttribute(epqstate->origslot,
2989  aerm->wholeAttNo,
2990  &isNull);
2991  /* non-locked rels could be on the inside of outer joins */
2992  if (isNull)
2993  continue;
2994  td = DatumGetHeapTupleHeader(datum);
2995 
2996  /* build a temporary HeapTuple control structure */
2998  tuple.t_data = td;
2999  /* relation might be a foreign table, if so provide tableoid */
3000  tuple.t_tableOid = erm->relid;
3001  /* also copy t_ctid in case there's valid data there */
3002  tuple.t_self = td->t_ctid;
3003 
3004  /* copy and store tuple */
3005  EvalPlanQualSetTuple(epqstate, erm->rti,
3006  heap_copytuple(&tuple));
3007  }
3008  }
3009 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
void EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
Definition: execMain.c:2847
Relation relation
Definition: execnodes.h:553
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1899
#define DatumGetObjectId(X)
Definition: postgres.h:483
int errcode(int sqlerrcode)
Definition: elog.c:575
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:982
ItemPointerData * ItemPointer
Definition: itemptr.h:49
ExecRowMark * rowmark
Definition: execnodes.h:580
HeapTupleHeader t_data
Definition: htup.h:67
#define ERROR
Definition: elog.h:43
ItemPointerData t_ctid
Definition: htup_details.h:155
ItemPointerData t_self
Definition: htup.h:65
List * arowMarks
Definition: execnodes.h:939
uint32 t_len
Definition: htup.h:64
Index rti
Definition: execnodes.h:555
AttrNumber wholeAttNo
Definition: execnodes.h:583
Index prti
Definition: execnodes.h:556
#define RelationGetRelationName(relation)
Definition: rel.h:445
Oid t_tableOid
Definition: htup.h:66
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
TupleTableSlot * origslot
Definition: execnodes.h:937
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:365
#define SnapshotAny
Definition: tqual.h:28
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
RowMarkType markType
Definition: execnodes.h:558
AttrNumber toidAttNo
Definition: execnodes.h:582
#define DatumGetPointer(X)
Definition: postgres.h:532
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:935
int Buffer
Definition: buf.h:23
AttrNumber ctidAttNo
Definition: execnodes.h:581
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:215
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:444

◆ EvalPlanQualGetTuple()

HeapTuple EvalPlanQualGetTuple ( EPQState epqstate,
Index  rti 
)

Definition at line 2867 of file execMain.c.

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

2868 {
2869  EState *estate = epqstate->estate;
2870 
2871  Assert(rti > 0);
2872 
2873  return estate->es_epqTuple[rti - 1];
2874 }
HeapTuple * es_epqTuple
Definition: execnodes.h:523
#define Assert(condition)
Definition: c.h:688
EState * estate
Definition: execnodes.h:935

◆ EvalPlanQualInit()

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

Definition at line 2812 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().

2814 {
2815  /* Mark the EPQ state inactive */
2816  epqstate->estate = NULL;
2817  epqstate->planstate = NULL;
2818  epqstate->origslot = NULL;
2819  /* ... and remember data that EvalPlanQualBegin will need */
2820  epqstate->plan = subplan;
2821  epqstate->arowMarks = auxrowmarks;
2822  epqstate->epqParam = epqParam;
2823 }
PlanState * planstate
Definition: execnodes.h:936
List * arowMarks
Definition: execnodes.h:939
TupleTableSlot * origslot
Definition: execnodes.h:937
Plan * plan
Definition: execnodes.h:938
int epqParam
Definition: execnodes.h:940
EState * estate
Definition: execnodes.h:935

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 3017 of file execMain.c.

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

Referenced by EvalPlanQual(), and ExecLockRows().

3018 {
3019  MemoryContext oldcontext;
3020  TupleTableSlot *slot;
3021 
3022  oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
3023  slot = ExecProcNode(epqstate->planstate);
3024  MemoryContextSwitchTo(oldcontext);
3025 
3026  return slot;
3027 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:936
MemoryContext es_query_cxt
Definition: execnodes.h:488
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:234
EState * estate
Definition: execnodes.h:935

◆ EvalPlanQualSetPlan()

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

Definition at line 2831 of file execMain.c.

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

Referenced by ExecInitModifyTable(), and ExecModifyTable().

2832 {
2833  /* If we have a live EPQ query, shut it down */
2834  EvalPlanQualEnd(epqstate);
2835  /* And set/change the plan pointer */
2836  epqstate->plan = subplan;
2837  /* The rowmarks depend on the plan, too */
2838  epqstate->arowMarks = auxrowmarks;
2839 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3226
List * arowMarks
Definition: execnodes.h:939
Plan * plan
Definition: execnodes.h:938

◆ EvalPlanQualSetTuple()

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

Definition at line 2847 of file execMain.c.

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

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

2848 {
2849  EState *estate = epqstate->estate;
2850 
2851  Assert(rti > 0);
2852 
2853  /*
2854  * free old test tuple, if any, and store new tuple where relation's scan
2855  * node will see it
2856  */
2857  if (estate->es_epqTuple[rti - 1] != NULL)
2858  heap_freetuple(estate->es_epqTuple[rti - 1]);
2859  estate->es_epqTuple[rti - 1] = tuple;
2860  estate->es_epqTupleSet[rti - 1] = true;
2861 }
HeapTuple * es_epqTuple
Definition: execnodes.h:523
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define Assert(condition)
Definition: c.h:688
bool * es_epqTupleSet
Definition: execnodes.h:524
EState * estate
Definition: execnodes.h:935

◆ EvalPlanQualStart()

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

Definition at line 3085 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().

3086 {
3087  EState *estate;
3088  int rtsize;
3089  MemoryContext oldcontext;
3090  ListCell *l;
3091 
3092  rtsize = list_length(parentestate->es_range_table);
3093 
3094  epqstate->estate = estate = CreateExecutorState();
3095 
3096  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3097 
3098  /*
3099  * Child EPQ EStates share the parent's copy of unchanging state such as
3100  * the snapshot, rangetable, result-rel info, and external Param info.
3101  * They need their own copies of local state, including a tuple table,
3102  * es_param_exec_vals, etc.
3103  *
3104  * The ResultRelInfo array management is trickier than it looks. We
3105  * create a fresh array for the child but copy all the content from the
3106  * parent. This is because it's okay for the child to share any
3107  * per-relation state the parent has already created --- but if the child
3108  * sets up any ResultRelInfo fields, such as its own junkfilter, that
3109  * state must *not* propagate back to the parent. (For one thing, the
3110  * pointed-to data is in a memory context that won't last long enough.)
3111  */
3113  estate->es_snapshot = parentestate->es_snapshot;
3114  estate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
3115  estate->es_range_table = parentestate->es_range_table;
3116  estate->es_plannedstmt = parentestate->es_plannedstmt;
3117  estate->es_junkFilter = parentestate->es_junkFilter;
3118  estate->es_output_cid = parentestate->es_output_cid;
3119  if (parentestate->es_num_result_relations > 0)
3120  {
3121  int numResultRelations = parentestate->es_num_result_relations;
3122  ResultRelInfo *resultRelInfos;
3123 
3124  resultRelInfos = (ResultRelInfo *)
3125  palloc(numResultRelations * sizeof(ResultRelInfo));
3126  memcpy(resultRelInfos, parentestate->es_result_relations,
3127  numResultRelations * sizeof(ResultRelInfo));
3128  estate->es_result_relations = resultRelInfos;
3129  estate->es_num_result_relations = numResultRelations;
3130  }
3131  /* es_result_relation_info must NOT be copied */
3132  /* es_trig_target_relations must NOT be copied */
3133  estate->es_rowMarks = parentestate->es_rowMarks;
3134  estate->es_top_eflags = parentestate->es_top_eflags;
3135  estate->es_instrument = parentestate->es_instrument;
3136  /* es_auxmodifytables must NOT be copied */
3137 
3138  /*
3139  * The external param list is simply shared from parent. The internal
3140  * param workspace has to be local state, but we copy the initial values
3141  * from the parent, so as to have access to any param values that were
3142  * already set from other parts of the parent's plan tree.
3143  */
3144  estate->es_param_list_info = parentestate->es_param_list_info;
3145  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
3146  {
3147  int i;
3148 
3149  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
3150  estate->es_param_exec_vals = (ParamExecData *)
3151  palloc0(i * sizeof(ParamExecData));
3152  while (--i >= 0)
3153  {
3154  /* copy value if any, but not execPlan link */
3155  estate->es_param_exec_vals[i].value =
3156  parentestate->es_param_exec_vals[i].value;
3157  estate->es_param_exec_vals[i].isnull =
3158  parentestate->es_param_exec_vals[i].isnull;
3159  }
3160  }
3161 
3162  /*
3163  * Each EState must have its own es_epqScanDone state, but if we have
3164  * nested EPQ checks they should share es_epqTuple arrays. This allows
3165  * sub-rechecks to inherit the values being examined by an outer recheck.
3166  */
3167  estate->es_epqScanDone = (bool *) palloc0(rtsize * sizeof(bool));
3168  if (parentestate->es_epqTuple != NULL)
3169  {
3170  estate->es_epqTuple = parentestate->es_epqTuple;
3171  estate->es_epqTupleSet = parentestate->es_epqTupleSet;
3172  }
3173  else
3174  {
3175  estate->es_epqTuple = (HeapTuple *)
3176  palloc0(rtsize * sizeof(HeapTuple));
3177  estate->es_epqTupleSet = (bool *)
3178  palloc0(rtsize * sizeof(bool));
3179  }
3180 
3181  /*
3182  * Each estate also has its own tuple table.
3183  */
3184  estate->es_tupleTable = NIL;
3185 
3186  /*
3187  * Initialize private state information for each SubPlan. We must do this
3188  * before running ExecInitNode on the main query tree, since
3189  * ExecInitSubPlan expects to be able to find these entries. Some of the
3190  * SubPlans might not be used in the part of the plan tree we intend to
3191  * run, but since it's not easy to tell which, we just initialize them
3192  * all.
3193  */
3194  Assert(estate->es_subplanstates == NIL);
3195  foreach(l, parentestate->es_plannedstmt->subplans)
3196  {
3197  Plan *subplan = (Plan *) lfirst(l);
3198  PlanState *subplanstate;
3199 
3200  subplanstate = ExecInitNode(subplan, estate, 0);
3201  estate->es_subplanstates = lappend(estate->es_subplanstates,
3202  subplanstate);
3203  }
3204 
3205  /*
3206  * Initialize the private state information for all the nodes in the part
3207  * of the plan tree we need to run. This opens files, allocates storage
3208  * and leaves us ready to start processing tuples.
3209  */
3210  epqstate->planstate = ExecInitNode(planTree, estate, 0);
3211 
3212  MemoryContextSwitchTo(oldcontext);
3213 }
List * paramExecTypes
Definition: plannodes.h:92
#define NIL
Definition: pg_list.h:69
HeapTuple * es_epqTuple
Definition: execnodes.h:523
JunkFilter * es_junkFilter
Definition: execnodes.h:449
CommandId es_output_cid
Definition: execnodes.h:452
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlannedStmt * es_plannedstmt
Definition: execnodes.h:446
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:444
Snapshot es_snapshot
Definition: execnodes.h:443
List * es_range_table
Definition: execnodes.h:445
PlanState * planstate
Definition: execnodes.h:936
ScanDirection es_direction
Definition: execnodes.h:442
ParamExecData * es_param_exec_vals
Definition: execnodes.h:483
MemoryContext es_query_cxt
Definition: execnodes.h:488
bool isnull
Definition: params.h:149
ResultRelInfo * es_result_relations
Definition: execnodes.h:455
int es_instrument
Definition: execnodes.h:498
EState * CreateExecutorState(void)
Definition: execUtils.c:80
List * lappend(List *list, void *datum)
Definition: list.c:128
List * es_tupleTable
Definition: execnodes.h:490
void * palloc0(Size size)
Definition: mcxt.c:864
int es_num_result_relations
Definition: execnodes.h:456
List * subplans
Definition: plannodes.h:81
#define Assert(condition)
Definition: c.h:688
#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:524
List * es_subplanstates
Definition: execnodes.h:503
List * es_rowMarks
Definition: execnodes.h:492
void * palloc(Size size)
Definition: mcxt.c:835
int es_top_eflags
Definition: execnodes.h:497
int i
bool * es_epqScanDone
Definition: execnodes.h:525
Datum value
Definition: params.h:148
ParamListInfo es_param_list_info
Definition: execnodes.h:482
EState * estate
Definition: execnodes.h:935
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2425 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().

2426 {
2427  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2428  char resname[32];
2429 
2430  aerm->rowmark = erm;
2431 
2432  /* Look up the resjunk columns associated with this rowmark */
2433  if (erm->markType != ROW_MARK_COPY)
2434  {
2435  /* need ctid for all methods other than COPY */
2436  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2437  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2438  resname);
2439  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2440  elog(ERROR, "could not find junk %s column", resname);
2441  }
2442  else
2443  {
2444  /* need wholerow if COPY */
2445  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2446  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2447  resname);
2448  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2449  elog(ERROR, "could not find junk %s column", resname);
2450  }
2451 
2452  /* if child rel, need tableoid */
2453  if (erm->rti != erm->prti)
2454  {
2455  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2456  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2457  resname);
2458  if (!AttributeNumberIsValid(aerm->toidAttNo))
2459  elog(ERROR, "could not find junk %s column", resname);
2460  }
2461 
2462  return aerm;
2463 }
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:580
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:555
AttrNumber wholeAttNo
Definition: execnodes.h:583
Index prti
Definition: execnodes.h:556
Index rowmarkId
Definition: execnodes.h:557
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void * palloc0(Size size)
Definition: mcxt.c:864
RowMarkType markType
Definition: execnodes.h:558
AttrNumber toidAttNo
Definition: execnodes.h:582
#define elog
Definition: elog.h:219
AttrNumber ctidAttNo
Definition: execnodes.h:581

◆ ExecBuildSlotValueDescription()

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

Definition at line 2238 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().

2243 {
2245  StringInfoData collist;
2246  bool write_comma = false;
2247  bool write_comma_collist = false;
2248  int i;
2249  AclResult aclresult;
2250  bool table_perm = false;
2251  bool any_perm = false;
2252 
2253  /*
2254  * Check if RLS is enabled and should be active for the relation; if so,
2255  * then don't return anything. Otherwise, go through normal permission
2256  * checks.
2257  */
2258  if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2259  return NULL;
2260 
2261  initStringInfo(&buf);
2262 
2263  appendStringInfoChar(&buf, '(');
2264 
2265  /*
2266  * Check if the user has permissions to see the row. Table-level SELECT
2267  * allows access to all columns. If the user does not have table-level
2268  * SELECT then we check each column and include those the user has SELECT
2269  * rights on. Additionally, we always include columns the user provided
2270  * data for.
2271  */
2272  aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2273  if (aclresult != ACLCHECK_OK)
2274  {
2275  /* Set up the buffer for the column list */
2276  initStringInfo(&collist);
2277  appendStringInfoChar(&collist, '(');
2278  }
2279  else
2280  table_perm = any_perm = true;
2281 
2282  /* Make sure the tuple is fully deconstructed */
2283  slot_getallattrs(slot);
2284 
2285  for (i = 0; i < tupdesc->natts; i++)
2286  {
2287  bool column_perm = false;
2288  char *val;
2289  int vallen;
2290  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2291 
2292  /* ignore dropped columns */
2293  if (att->attisdropped)
2294  continue;
2295 
2296  if (!table_perm)
2297  {
2298  /*
2299  * No table-level SELECT, so need to make sure they either have
2300  * SELECT rights on the column or that they have provided the data
2301  * for the column. If not, omit this column from the error
2302  * message.
2303  */
2304  aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2305  GetUserId(), ACL_SELECT);
2307  modifiedCols) || aclresult == ACLCHECK_OK)
2308  {
2309  column_perm = any_perm = true;
2310 
2311  if (write_comma_collist)
2312  appendStringInfoString(&collist, ", ");
2313  else
2314  write_comma_collist = true;
2315 
2316  appendStringInfoString(&collist, NameStr(att->attname));
2317  }
2318  }
2319 
2320  if (table_perm || column_perm)
2321  {
2322  if (slot->tts_isnull[i])
2323  val = "null";
2324  else
2325  {
2326  Oid foutoid;
2327  bool typisvarlena;
2328 
2329  getTypeOutputInfo(att->atttypid,
2330  &foutoid, &typisvarlena);
2331  val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2332  }
2333 
2334  if (write_comma)
2335  appendStringInfoString(&buf, ", ");
2336  else
2337  write_comma = true;
2338 
2339  /* truncate if needed */
2340  vallen = strlen(val);
2341  if (vallen <= maxfieldlen)
2342  appendStringInfoString(&buf, val);
2343  else
2344  {
2345  vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2346  appendBinaryStringInfo(&buf, val, vallen);
2347  appendStringInfoString(&buf, "...");
2348  }
2349  }
2350  }
2351 
2352  /* If we end up with zero columns being returned, then return NULL. */
2353  if (!any_perm)
2354  return NULL;
2355 
2356  appendStringInfoChar(&buf, ')');
2357 
2358  if (!table_perm)
2359  {
2360  appendStringInfoString(&collist, ") = ");
2361  appendStringInfoString(&collist, buf.data);
2362 
2363  return collist.data;
2364  }
2365 
2366  return buf.data;
2367 }
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:4514
Oid GetUserId(void)
Definition: miscinit.c:284
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
Datum * tts_values
Definition: tuptable.h:125
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:79
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:126
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
void slot_getallattrs(TupleTableSlot *slot)
Definition: heaptuple.c:1238
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:73
#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:4628
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1742
int i
#define NameStr(name)
Definition: c.h:565
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:464
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 599 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().

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

◆ ExecCheckRTEPermsModified()

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

Definition at line 719 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().

721 {
722  int col = -1;
723 
724  /*
725  * When the query doesn't explicitly update any columns, allow the query
726  * if we have permission on any column of the rel. This is to handle
727  * SELECT FOR UPDATE as well as possible corner cases in UPDATE.
728  */
729  if (bms_is_empty(modifiedCols))
730  {
731  if (pg_attribute_aclcheck_all(relOid, userid, requiredPerms,
733  return false;
734  }
735 
736  while ((col = bms_next_member(modifiedCols, col)) >= 0)
737  {
738  /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
740 
741  if (attno == InvalidAttrNumber)
742  {
743  /* whole-row reference can't happen here */
744  elog(ERROR, "whole-row update is not implemented");
745  }
746  else
747  {
748  if (pg_attribute_aclcheck(relOid, attno, userid,
749  requiredPerms) != ACLCHECK_OK)
750  return false;
751  }
752  }
753  return true;
754 }
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4514
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1053
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define ERROR
Definition: elog.h:43
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:707
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4543
#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 568 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().

569 {
570  ListCell *l;
571  bool result = true;
572 
573  foreach(l, rangeTable)
574  {
575  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
576 
577  result = ExecCheckRTEPerms(rte);
578  if (!result)
579  {
580  Assert(rte->rtekind == RTE_RELATION);
581  if (ereport_on_violation)
583  get_rel_name(rte->relid));
584  return false;
585  }
586  }
587 
589  result = (*ExecutorCheckPerms_hook) (rangeTable,
590  ereport_on_violation);
591  return result;
592 }
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
static bool ExecCheckRTEPerms(RangeTblEntry *rte)
Definition: execMain.c:599
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:75
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
RTEKind rtekind
Definition: parsenodes.h:959
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 766 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().

767 {
768  ListCell *l;
769 
770  /*
771  * Fail if write permissions are requested in parallel mode for table
772  * (temp or non-temp), otherwise fail for any non-temp table.
773  */
774  foreach(l, plannedstmt->rtable)
775  {
776  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
777 
778  if (rte->rtekind != RTE_RELATION)
779  continue;
780 
781  if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
782  continue;
783 
785  continue;
786 
788  }
789 
790  if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
792 }
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:255
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1754
Definition: nodes.h:513
AclMode requiredPerms
Definition: parsenodes.h:1067
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3118
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2071
CmdType commandType
Definition: plannodes.h:45
#define ACL_SELECT
Definition: parsenodes.h:73
#define lfirst(lc)
Definition: pg_list.h:106
bool hasModifyingCTE
Definition: plannodes.h:51
List * rtable
Definition: plannodes.h:63
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:237
RTEKind rtekind
Definition: parsenodes.h:959

◆ ExecCleanUpTriggerState()

void ExecCleanUpTriggerState ( EState estate)

Definition at line 1469 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().

1470 {
1471  ListCell *l;
1472 
1473  foreach(l, estate->es_trig_target_relations)
1474  {
1475  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1476 
1477  /* Close indices and then the relation itself */
1478  ExecCloseIndices(resultRelInfo);
1479  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1480  }
1481 }
Relation ri_RelationDesc
Definition: execnodes.h:368
#define heap_close(r, l)
Definition: heapam.h:97
#define NoLock
Definition: lockdefs.h:34
List * es_trig_target_relations
Definition: execnodes.h:476
#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,
bool  check_partition_constraint 
)

Definition at line 1957 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(), ExecPartitionCheck(), ExecPartitionCheckEmitError(), 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().

1960 {
1961  Relation rel = resultRelInfo->ri_RelationDesc;
1962  TupleDesc tupdesc = RelationGetDescr(rel);
1963  TupleConstr *constr = tupdesc->constr;
1964  Bitmapset *modifiedCols;
1965  Bitmapset *insertedCols;
1966  Bitmapset *updatedCols;
1967 
1968  Assert(constr || resultRelInfo->ri_PartitionCheck);
1969 
1970  if (constr && constr->has_not_null)
1971  {
1972  int natts = tupdesc->natts;
1973  int attrChk;
1974 
1975  for (attrChk = 1; attrChk <= natts; attrChk++)
1976  {
1977  Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
1978 
1979  if (att->attnotnull && slot_attisnull(slot, attrChk))
1980  {
1981  char *val_desc;
1982  Relation orig_rel = rel;
1983  TupleDesc orig_tupdesc = RelationGetDescr(rel);
1984 
1985  /*
1986  * If the tuple has been routed, it's been converted to the
1987  * partition's rowtype, which might differ from the root
1988  * table's. We must convert it back to the root table's
1989  * rowtype so that val_desc shown error message matches the
1990  * input tuple.
1991  */
1992  if (resultRelInfo->ri_PartitionRoot)
1993  {
1994  HeapTuple tuple = ExecFetchSlotTuple(slot);
1995  TupleConversionMap *map;
1996 
1997  rel = resultRelInfo->ri_PartitionRoot;
1998  tupdesc = RelationGetDescr(rel);
1999  /* a reverse map */
2000  map = convert_tuples_by_name(orig_tupdesc, tupdesc,
2001  gettext_noop("could not convert row type"));
2002  if (map != NULL)
2003  {
2004  tuple = do_convert_tuple(tuple, map);
2005  ExecSetSlotDescriptor(slot, tupdesc);
2006  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2007  }
2008  }
2009 
2010  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2011  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2012  modifiedCols = bms_union(insertedCols, updatedCols);
2014  slot,
2015  tupdesc,
2016  modifiedCols,
2017  64);
2018 
2019  ereport(ERROR,
2020  (errcode(ERRCODE_NOT_NULL_VIOLATION),
2021  errmsg("null value in column \"%s\" violates not-null constraint",
2022  NameStr(att->attname)),
2023  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2024  errtablecol(orig_rel, attrChk)));
2025  }
2026  }
2027  }
2028 
2029  if (constr && constr->num_check > 0)
2030  {
2031  const char *failed;
2032 
2033  if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2034  {
2035  char *val_desc;
2036  Relation orig_rel = rel;
2037 
2038  /* See the comment above. */
2039  if (resultRelInfo->ri_PartitionRoot)
2040  {
2041  HeapTuple tuple = ExecFetchSlotTuple(slot);
2042  TupleDesc old_tupdesc = RelationGetDescr(rel);
2043  TupleConversionMap *map;
2044 
2045  rel = resultRelInfo->ri_PartitionRoot;
2046  tupdesc = RelationGetDescr(rel);
2047  /* a reverse map */
2048  map = convert_tuples_by_name(old_tupdesc, tupdesc,
2049  gettext_noop("could not convert row type"));
2050  if (map != NULL)
2051  {
2052  tuple = do_convert_tuple(tuple, map);
2053  ExecSetSlotDescriptor(slot, tupdesc);
2054  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2055  }
2056  }
2057 
2058  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2059  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2060  modifiedCols = bms_union(insertedCols, updatedCols);
2062  slot,
2063  tupdesc,
2064  modifiedCols,
2065  64);
2066  ereport(ERROR,
2067  (errcode(ERRCODE_CHECK_VIOLATION),
2068  errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2069  RelationGetRelationName(orig_rel), failed),
2070  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2071  errtableconstraint(orig_rel, failed)));
2072  }
2073  }
2074 
2075  if (check_partition_constraint && resultRelInfo->ri_PartitionCheck &&
2076  !ExecPartitionCheck(resultRelInfo, slot, estate))
2077  ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
2078 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
Relation ri_RelationDesc
Definition: execnodes.h:368
#define RelationGetDescr(relation)
Definition: rel.h:437
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
Relation ri_PartitionRoot
Definition: execnodes.h:428
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:1025
int errcode(int sqlerrcode)
Definition: elog.c:575
int natts
Definition: tupdesc.h:79
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5281
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2238
int errdetail(const char *fmt,...)
Definition: elog.c:873
void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1896
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
bool has_not_null
Definition: tupdesc.h:43
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:422
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1793
bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1329
#define Assert(condition)
Definition: c.h:688
int errtablecol(Relation rel, int attnum)
Definition: relcache.c:5244
TupleConstr * constr
Definition: tupdesc.h:84
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:262
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:654
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:565
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1858
uint16 num_check
Definition: tupdesc.h:42
#define RelationGetRelid(relation)
Definition: rel.h:425
#define GetInsertedColumns(relinfo, estate)
Definition: execMain.c:109

◆ ExecContextForcesOids()

bool ExecContextForcesOids ( PlanState planstate,
bool hasoids 
)

Definition at line 1516 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().

1517 {
1518  ResultRelInfo *ri = planstate->state->es_result_relation_info;
1519 
1520  if (ri != NULL)
1521  {
1522  Relation rel = ri->ri_RelationDesc;
1523 
1524  if (rel != NULL)
1525  {
1526  *hasoids = rel->rd_rel->relhasoids;
1527  return true;
1528  }
1529  }
1530 
1531  if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS)
1532  {
1533  *hasoids = true;
1534  return true;
1535  }
1536  if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS)
1537  {
1538  *hasoids = false;
1539  return true;
1540  }
1541 
1542  return false;
1543 }
Relation ri_RelationDesc
Definition: execnodes.h:368
EState * state
Definition: execnodes.h:870
Form_pg_class rd_rel
Definition: rel.h:114
#define EXEC_FLAG_WITHOUT_OIDS
Definition: executor.h:65
#define EXEC_FLAG_WITH_OIDS
Definition: executor.h:64
int es_top_eflags
Definition: execnodes.h:497
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:457

◆ ExecEndPlan()

static void ExecEndPlan ( PlanState planstate,
EState estate 
)
static

Definition at line 1598 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().

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

◆ ExecFindRowMark()

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

Definition at line 2401 of file execMain.c.

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

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

2402 {
2403  ListCell *lc;
2404 
2405  foreach(lc, estate->es_rowMarks)
2406  {
2407  ExecRowMark *erm = (ExecRowMark *) lfirst(lc);
2408 
2409  if (erm->rti == rti)
2410  return erm;
2411  }
2412  if (!missing_ok)
2413  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2414  return NULL;
2415 }
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:555
#define lfirst(lc)
Definition: pg_list.h:106
List * es_rowMarks
Definition: execnodes.h:492
#define elog
Definition: elog.h:219

◆ ExecGetTriggerResultRel()

ResultRelInfo* ExecGetTriggerResultRel ( EState estate,
Oid  relid 
)

Definition at line 1388 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().

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

◆ ExecPartitionCheck()

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

Definition at line 1858 of file execMain.c.

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

Referenced by ExecConstraints(), ExecFindPartition(), and ExecUpdate().

1860 {
1861  ExprContext *econtext;
1862 
1863  /*
1864  * If first time through, build expression state tree for the partition
1865  * check expression. Keep it in the per-query memory context so they'll
1866  * survive throughout the query.
1867  */
1868  if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1869  {
1870  List *qual = resultRelInfo->ri_PartitionCheck;
1871 
1872  resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1873  }
1874 
1875  /*
1876  * We will use the EState's per-tuple context for evaluating constraint
1877  * expressions (creating it if it's not already there).
1878  */
1879  econtext = GetPerTupleExprContext(estate);
1880 
1881  /* Arrange for econtext's scan tuple to be the tuple under test */
1882  econtext->ecxt_scantuple = slot;
1883 
1884  /*
1885  * As in case of the catalogued constraints, we treat a NULL result as
1886  * success here, not a failure.
1887  */
1888  return ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
1889 }
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:538
ExprState * ri_PartitionCheckExpr
Definition: execnodes.h:425
#define GetPerTupleExprContext(estate)
Definition: executor.h:490
List * ri_PartitionCheck
Definition: execnodes.h:422
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:211
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:594
Definition: pg_list.h:45

◆ ExecPartitionCheckEmitError()

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

Definition at line 1896 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 ExecConstraints(), ExecFindPartition(), and ExecUpdate().

1899 {
1900  Relation rel = resultRelInfo->ri_RelationDesc;
1901  Relation orig_rel = rel;
1902  TupleDesc tupdesc = RelationGetDescr(rel);
1903  char *val_desc;
1904  Bitmapset *modifiedCols;
1905  Bitmapset *insertedCols;
1906  Bitmapset *updatedCols;
1907 
1908  /*
1909  * Need to first convert the tuple to the root partitioned table's row
1910  * type. For details, check similar comments in ExecConstraints().
1911  */
1912  if (resultRelInfo->ri_PartitionRoot)
1913  {
1914  HeapTuple tuple = ExecFetchSlotTuple(slot);
1915  TupleDesc old_tupdesc = RelationGetDescr(rel);
1916  TupleConversionMap *map;
1917 
1918  rel = resultRelInfo->ri_PartitionRoot;
1919  tupdesc = RelationGetDescr(rel);
1920  /* a reverse map */
1921  map = convert_tuples_by_name(old_tupdesc, tupdesc,
1922  gettext_noop("could not convert row type"));
1923  if (map != NULL)
1924  {
1925  tuple = do_convert_tuple(tuple, map);
1926  ExecSetSlotDescriptor(slot, tupdesc);
1927  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
1928  }
1929  }
1930 
1931  insertedCols = GetInsertedColumns(resultRelInfo, estate);
1932  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
1933  modifiedCols = bms_union(insertedCols, updatedCols);
1935  slot,
1936  tupdesc,
1937  modifiedCols,
1938  64);
1939  ereport(ERROR,
1940  (errcode(ERRCODE_CHECK_VIOLATION),
1941  errmsg("new row for relation \"%s\" violates partition constraint",
1942  RelationGetRelationName(orig_rel)),
1943  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
1944 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
Relation ri_RelationDesc
Definition: execnodes.h:368
#define RelationGetDescr(relation)
Definition: rel.h:437
Relation ri_PartitionRoot
Definition: execnodes.h:428
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:1025
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:2238
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:445
#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:262
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:654
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RelationGetRelid(relation)
Definition: rel.h:425
#define GetInsertedColumns(relinfo, estate)
Definition: execMain.c:109

◆ ExecPostprocessPlan()

static void ExecPostprocessPlan ( EState estate)
static

Definition at line 1552 of file execMain.c.

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

Referenced by standard_ExecutorFinish().

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

◆ ExecRelCheck()

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

Definition at line 1793 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().

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

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2375 of file execMain.c.

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

Referenced by ExecBRUpdateTriggers(), and ExecOnConflictUpdate().

2376 {
2377  Bitmapset *keyCols;
2378  Bitmapset *updatedCols;
2379 
2380  /*
2381  * Compute lock mode to use. If columns that are part of the key have not
2382  * been modified, then we can use a weaker lock, allowing for better
2383  * concurrency.
2384  */
2385  updatedCols = GetUpdatedColumns(relinfo, estate);
2386  keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2388 
2389  if (bms_overlap(keyCols, updatedCols))
2390  return LockTupleExclusive;
2391 
2392  return LockTupleNoKeyExclusive;
2393 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
Relation ri_RelationDesc
Definition: execnodes.h:368
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:487
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:4831

◆ 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 1676 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().

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

◆ ExecutorEnd()

void ExecutorEnd ( QueryDesc queryDesc)

Definition at line 459 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().

460 {
461  if (ExecutorEnd_hook)
462  (*ExecutorEnd_hook) (queryDesc);
463  else
464  standard_ExecutorEnd(queryDesc);
465 }
void standard_ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:468
ExecutorEnd_hook_type ExecutorEnd_hook
Definition: execMain.c:72

◆ ExecutorFinish()

void ExecutorFinish ( QueryDesc queryDesc)

Definition at line 399 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().

400 {
402  (*ExecutorFinish_hook) (queryDesc);
403  else
404  standard_ExecutorFinish(queryDesc);
405 }
void standard_ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:408
ExecutorFinish_hook_type ExecutorFinish_hook
Definition: execMain.c:71

◆ ExecutorRewind()

void ExecutorRewind ( QueryDesc queryDesc)

Definition at line 525 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().

526 {
527  EState *estate;
528  MemoryContext oldcontext;
529 
530  /* sanity checks */
531  Assert(queryDesc != NULL);
532 
533  estate = queryDesc->estate;
534 
535  Assert(estate != NULL);
536 
537  /* It's probably not sensible to rescan updating queries */
538  Assert(queryDesc->operation == CMD_SELECT);
539 
540  /*
541  * Switch into per-query memory context
542  */
543  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
544 
545  /*
546  * rescan plan
547  */
548  ExecReScan(queryDesc->planstate);
549 
550  MemoryContextSwitchTo(oldcontext);
551 }
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:488
PlanState * planstate
Definition: execdesc.h:49
CmdType operation
Definition: execdesc.h:36
#define Assert(condition)
Definition: c.h:688

◆ ExecutorRun()

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

Definition at line 297 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().

300 {
301  if (ExecutorRun_hook)
302  (*ExecutorRun_hook) (queryDesc, direction, count, execute_once);
303  else
304  standard_ExecutorRun(queryDesc, direction, count, execute_once);
305 }
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:308
ExecutorRun_hook_type ExecutorRun_hook
Definition: execMain.c:70

◆ ExecutorStart()

void ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 140 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().

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

◆ ExecWithCheckOptions()

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

Definition at line 2091 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().

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

◆ InitPlan()

static void InitPlan ( QueryDesc queryDesc,
int  eflags 
)
static

Definition at line 803 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().

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

◆ InitResultRelInfo()

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

Definition at line 1306 of file execMain.c.

References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), MemSet, NIL, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, RelationGetPartitionQual(), RELKIND_FOREIGN_TABLE, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_PartitionCheck, 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(), ExecSetupPartitionTupleRouting(), ExecuteTruncate(), and InitPlan().

1311 {
1312  List *partition_check = NIL;
1313 
1314  MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1315  resultRelInfo->type = T_ResultRelInfo;
1316  resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1317  resultRelInfo->ri_RelationDesc = resultRelationDesc;
1318  resultRelInfo->ri_NumIndices = 0;
1319  resultRelInfo->ri_IndexRelationDescs = NULL;
1320  resultRelInfo->ri_IndexRelationInfo = NULL;
1321  /* make a copy so as not to depend on relcache info not changing... */
1322  resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1323  if (resultRelInfo->ri_TrigDesc)
1324  {
1325  int n = resultRelInfo->ri_TrigDesc->numtriggers;
1326 
1327  resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1328  palloc0(n * sizeof(FmgrInfo));
1329  resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1330  palloc0(n * sizeof(ExprState *));
1331  if (instrument_options)
1332  resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options);
1333  }
1334  else
1335  {
1336  resultRelInfo->ri_TrigFunctions = NULL;
1337  resultRelInfo->ri_TrigWhenExprs = NULL;
1338  resultRelInfo->ri_TrigInstrument = NULL;
1339  }
1340  if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1341  resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
1342  else
1343  resultRelInfo->ri_FdwRoutine = NULL;
1344  resultRelInfo->ri_FdwState = NULL;
1345  resultRelInfo->ri_usesFdwDirectModify = false;
1346  resultRelInfo->ri_ConstraintExprs = NULL;
1347  resultRelInfo->ri_junkFilter = NULL;
1348  resultRelInfo->ri_projectReturning = NULL;
1349 
1350  /*
1351  * Partition constraint, which also includes the partition constraint of
1352  * all the ancestors that are partitions. Note that it will be checked
1353  * even in the case of tuple-routing where this table is the target leaf
1354  * partition, if there any BR triggers defined on the table. Although
1355  * tuple-routing implicitly preserves the partition constraint of the
1356  * target partition for a given row, the BR triggers may change the row
1357  * such that the constraint is no longer satisfied, which we must fail for
1358  * by checking it explicitly.
1359  *
1360  * If this is a partitioned table, the partition constraint (if any) of a
1361  * given row will be checked just before performing tuple-routing.
1362  */
1363  partition_check = RelationGetPartitionQual(resultRelationDesc);
1364 
1365  resultRelInfo->ri_PartitionCheck = partition_check;
1366  resultRelInfo->ri_PartitionRoot = partition_root;
1367 }
int ri_NumIndices
Definition: execnodes.h:371
#define NIL
Definition: pg_list.h:69
JunkFilter * ri_junkFilter
Definition: execnodes.h:410
Definition: fmgr.h:56
Relation ri_RelationDesc
Definition: execnodes.h:368
Relation ri_PartitionRoot
Definition: execnodes.h:428
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:389
Instrumentation * InstrAlloc(int n, int instrument_options)
Definition: instrument.c:30
#define MemSet(start, val, len)
Definition: c.h:897
Form_pg_class rd_rel
Definition: rel.h:114
Index ri_RangeTableIndex
Definition: execnodes.h:365
NodeTag type
Definition: execnodes.h:362
TriggerDesc * trigdesc
Definition: rel.h:120
bool ri_usesFdwDirectModify
Definition: execnodes.h:398
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:386
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:413
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:392
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:407
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:380
int numtriggers
Definition: reltrigger.h:49
List * RelationGetPartitionQual(Relation rel)
Definition: partition.c:1508
void * palloc0(Size size)
Definition: mcxt.c:864
List * ri_PartitionCheck
Definition: execnodes.h:422
void * ri_FdwState
Definition: execnodes.h:395
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:1911
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:377
Definition: pg_list.h:45
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:374
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:383

◆ standard_ExecutorEnd()

void standard_ExecutorEnd ( QueryDesc queryDesc)

Definition at line 468 of file execMain.c.

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

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

469 {
470  EState *estate;
471  MemoryContext oldcontext;
472 
473  /* sanity checks */
474  Assert(queryDesc != NULL);
475 
476  estate = queryDesc->estate;
477 
478  Assert(estate != NULL);
479 
480  /*
481  * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This
482  * Assert is needed because ExecutorFinish is new as of 9.1, and callers
483  * might forget to call it.
484  */
485  Assert(estate->es_finished ||
487 
488  /*
489  * Switch into per-query memory context to run ExecEndPlan
490  */
491  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
492 
493  ExecEndPlan(queryDesc->planstate, estate);
494 
495  /* do away with our snapshots */
498 
499  /*
500  * Must switch out of context before destroying it
501  */
502  MemoryContextSwitchTo(oldcontext);
503 
504  /*
505  * Release EState and per-query memory context. This should release
506  * everything the executor has allocated.
507  */
508  FreeExecutorState(estate);
509 
510  /* Reset queryDesc fields that no longer point to anything */
511  queryDesc->tupDesc = NULL;
512  queryDesc->estate = NULL;
513  queryDesc->planstate = NULL;
514  queryDesc->totaltime = NULL;
515 }
EState * estate
Definition: execdesc.h:48
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:444
Snapshot es_snapshot
Definition: execnodes.h:443
void FreeExecutorState(EState *estate)
Definition: execUtils.c:185
MemoryContext es_query_cxt
Definition: execnodes.h:488
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:499
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:688
static void ExecEndPlan(PlanState *planstate, EState *estate)
Definition: execMain.c:1598
int es_top_eflags
Definition: execnodes.h:497
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:59

◆ standard_ExecutorFinish()

void standard_ExecutorFinish ( QueryDesc queryDesc)

Definition at line 408 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().

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

◆ standard_ExecutorRun()

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

Definition at line 308 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().

310 {
311  EState *estate;
312  CmdType operation;
314  bool sendTuples;
315  MemoryContext oldcontext;
316 
317  /* sanity checks */
318  Assert(queryDesc != NULL);
319 
320  estate = queryDesc->estate;
321 
322  Assert(estate != NULL);
324 
325  /*
326  * Switch into per-query memory context
327  */
328  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
329 
330  /* Allow instrumentation of Executor overall runtime */
331  if (queryDesc->totaltime)
332  InstrStartNode(queryDesc->totaltime);
333 
334  /*
335  * extract information from the query descriptor and the query feature.
336  */
337  operation = queryDesc->operation;
338  dest = queryDesc->dest;
339 
340  /*
341  * startup tuple receiver, if we will be emitting tuples
342  */
343  estate->es_processed = 0;
344  estate->es_lastoid = InvalidOid;
345 
346  sendTuples = (operation == CMD_SELECT ||
347  queryDesc->plannedstmt->hasReturning);
348 
349  if (sendTuples)
350  dest->rStartup(dest, operation, queryDesc->tupDesc);
351 
352  /*
353  * run plan
354  */
355  if (!ScanDirectionIsNoMovement(direction))
356  {
357  if (execute_once && queryDesc->already_executed)
358  elog(ERROR, "can't re-execute query flagged for single execution");
359  queryDesc->already_executed = true;
360 
361  ExecutePlan(estate,
362  queryDesc->planstate,
363  queryDesc->plannedstmt->parallelModeNeeded,
364  operation,
365  sendTuples,
366  count,
367  direction,
368  dest,
369  execute_once);
370  }
371 
372  /*
373  * shutdown tuple receiver, if we started it
374  */
375  if (sendTuples)
376  dest->rShutdown(dest);
377 
378  if (queryDesc->totaltime)
379  InstrStopNode(queryDesc->totaltime, estate->es_processed);
380 
381  MemoryContextSwitchTo(oldcontext);
382 }
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:80
EState * estate
Definition: execdesc.h:48
Oid es_lastoid
Definition: execnodes.h:495
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:48
MemoryContext es_query_cxt
Definition: execnodes.h:488
#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:49
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:688
uint64 es_processed
Definition: execnodes.h:494
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
DestReceiver * dest
Definition: execdesc.h:41
int es_top_eflags
Definition: execnodes.h:497
bool parallelModeNeeded
Definition: plannodes.h:59
#define elog
Definition: elog.h:219
PlannedStmt * plannedstmt
Definition: execdesc.h:37
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:59
CmdType
Definition: nodes.h:653
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:1676

◆ standard_ExecutorStart()

void standard_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 149 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_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(), 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().

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

Variable Documentation

◆ ExecutorCheckPerms_hook

ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL

Definition at line 75 of file execMain.c.

Referenced by _PG_init(), and ExecCheckRTPerms().

◆ ExecutorEnd_hook

ExecutorEnd_hook_type ExecutorEnd_hook = NULL

Definition at line 72 of file execMain.c.

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

◆ ExecutorFinish_hook

ExecutorFinish_hook_type ExecutorFinish_hook = NULL

Definition at line 71 of file execMain.c.

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

◆ ExecutorRun_hook

ExecutorRun_hook_type ExecutorRun_hook = NULL

Definition at line 70 of file execMain.c.

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

◆ ExecutorStart_hook

ExecutorStart_hook_type ExecutorStart_hook = NULL

Definition at line 69 of file execMain.c.

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