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)
 
void ExecPartitionCheck (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
void ExecConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
void ExecWithCheckOptions (WCOKind kind, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
LockTupleMode ExecUpdateLockMode (EState *estate, ResultRelInfo *relinfo)
 
ExecRowMarkExecFindRowMark (EState *estate, Index rti, bool missing_ok)
 
ExecAuxRowMarkExecBuildAuxRowMark (ExecRowMark *erm, List *targetlist)
 
TupleTableSlotEvalPlanQual (EState *estate, EPQState *epqstate, Relation relation, Index rti, int lockmode, ItemPointer tid, TransactionId priorXmax)
 
HeapTuple EvalPlanQualFetch (EState *estate, Relation relation, int lockmode, LockWaitPolicy wait_policy, ItemPointer tid, TransactionId priorXmax)
 
void EvalPlanQualInit (EPQState *epqstate, EState *estate, Plan *subplan, List *auxrowmarks, int epqParam)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
void EvalPlanQualSetTuple (EPQState *epqstate, Index rti, HeapTuple tuple)
 
HeapTuple EvalPlanQualGetTuple (EPQState *epqstate, Index rti)
 
void EvalPlanQualFetchRowMarks (EPQState *epqstate)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate, EState *parentestate)
 
void EvalPlanQualEnd (EPQState *epqstate)
 

Variables

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

Macro Definition Documentation

◆ GetInsertedColumns

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

Definition at line 109 of file execMain.c.

Referenced by ExecConstraints(), ExecPartitionCheck(), 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:355
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:415
#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:379
#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 2478 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate,
EState parentestate 
)

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

3016 {
3017  EState *estate = epqstate->estate;
3018 
3019  if (estate == NULL)
3020  {
3021  /* First time through, so create a child EState */
3022  EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
3023  }
3024  else
3025  {
3026  /*
3027  * We already have a suitable child EPQ tree, so just reset it.
3028  */
3029  int rtsize = list_length(parentestate->es_range_table);
3030  PlanState *planstate = epqstate->planstate;
3031 
3032  MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
3033 
3034  /* Recopy current values of parent parameters */
3035  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
3036  {
3037  int i;
3038 
3039  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
3040 
3041  while (--i >= 0)
3042  {
3043  /* copy value if any, but not execPlan link */
3044  estate->es_param_exec_vals[i].value =
3045  parentestate->es_param_exec_vals[i].value;
3046  estate->es_param_exec_vals[i].isnull =
3047  parentestate->es_param_exec_vals[i].isnull;
3048  }
3049  }
3050 
3051  /*
3052  * Mark child plan tree as needing rescan at all scan nodes. The
3053  * first ExecProcNode will take care of actually doing the rescan.
3054  */
3055  planstate->chgParam = bms_add_member(planstate->chgParam,
3056  epqstate->epqParam);
3057  }
3058 }
List * paramExecTypes
Definition: plannodes.h:92
#define NIL
Definition: pg_list.h:69
PlannedStmt * es_plannedstmt
Definition: execnodes.h:433
#define MemSet(start, val, len)
Definition: c.h:853
List * es_range_table
Definition: execnodes.h:432
PlanState * planstate
Definition: execnodes.h:918
ParamExecData * es_param_exec_vals
Definition: execnodes.h:467
bool isnull
Definition: params.h:101
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
Definition: execMain.c:3067
Bitmapset * chgParam
Definition: execnodes.h:878
Plan * plan
Definition: execnodes.h:920
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
int i
bool * es_epqScanDone
Definition: execnodes.h:509
Datum value
Definition: params.h:100
int epqParam
Definition: execnodes.h:922
EState * estate
Definition: execnodes.h:917

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

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

3209 {
3210  EState *estate = epqstate->estate;
3211  MemoryContext oldcontext;
3212  ListCell *l;
3213 
3214  if (estate == NULL)
3215  return; /* idle, so nothing to do */
3216 
3217  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3218 
3219  ExecEndNode(epqstate->planstate);
3220 
3221  foreach(l, estate->es_subplanstates)
3222  {
3223  PlanState *subplanstate = (PlanState *) lfirst(l);
3224 
3225  ExecEndNode(subplanstate);
3226  }
3227 
3228  /* throw away the per-estate tuple table */
3229  ExecResetTupleTable(estate->es_tupleTable, false);
3230 
3231  /* close any trigger target relations attached to this EState */
3232  ExecCleanUpTriggerState(estate);
3233 
3234  MemoryContextSwitchTo(oldcontext);
3235 
3236  FreeExecutorState(estate);
3237 
3238  /* Mark EPQState idle */
3239  epqstate->estate = NULL;
3240  epqstate->planstate = NULL;
3241  epqstate->origslot = NULL;
3242 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:523
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:918
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
MemoryContext es_query_cxt
Definition: execnodes.h:472
TupleTableSlot * origslot
Definition: execnodes.h:919
List * es_tupleTable
Definition: execnodes.h:474
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:156
#define lfirst(lc)
Definition: pg_list.h:106
List * es_subplanstates
Definition: execnodes.h:487
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1466
EState * estate
Definition: execnodes.h:917

◆ EvalPlanQualFetch()

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

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

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

2865 {
2866  ListCell *l;
2867 
2868  Assert(epqstate->origslot != NULL);
2869 
2870  foreach(l, epqstate->arowMarks)
2871  {
2872  ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
2873  ExecRowMark *erm = aerm->rowmark;
2874  Datum datum;
2875  bool isNull;
2876  HeapTupleData tuple;
2877 
2879  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2880 
2881  /* clear any leftover test tuple for this rel */
2882  EvalPlanQualSetTuple(epqstate, erm->rti, NULL);
2883 
2884  /* if child rel, must check whether it produced this row */
2885  if (erm->rti != erm->prti)
2886  {
2887  Oid tableoid;
2888 
2889  datum = ExecGetJunkAttribute(epqstate->origslot,
2890  aerm->toidAttNo,
2891  &isNull);
2892  /* non-locked rels could be on the inside of outer joins */
2893  if (isNull)
2894  continue;
2895  tableoid = DatumGetObjectId(datum);
2896 
2897  Assert(OidIsValid(erm->relid));
2898  if (tableoid != erm->relid)
2899  {
2900  /* this child is inactive right now */
2901  continue;
2902  }
2903  }
2904 
2905  if (erm->markType == ROW_MARK_REFERENCE)
2906  {
2907  HeapTuple copyTuple;
2908 
2909  Assert(erm->relation != NULL);
2910 
2911  /* fetch the tuple's ctid */
2912  datum = ExecGetJunkAttribute(epqstate->origslot,
2913  aerm->ctidAttNo,
2914  &isNull);
2915  /* non-locked rels could be on the inside of outer joins */
2916  if (isNull)
2917  continue;
2918 
2919  /* fetch requests on foreign tables must be passed to their FDW */
2920  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2921  {
2922  FdwRoutine *fdwroutine;
2923  bool updated = false;
2924 
2925  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2926  /* this should have been checked already, but let's be safe */
2927  if (fdwroutine->RefetchForeignRow == NULL)
2928  ereport(ERROR,
2929  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2930  errmsg("cannot lock rows in foreign table \"%s\"",
2932  copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate,
2933  erm,
2934  datum,
2935  &updated);
2936  if (copyTuple == NULL)
2937  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2938 
2939  /*
2940  * Ideally we'd insist on updated == false here, but that
2941  * assumes that FDWs can track that exactly, which they might
2942  * not be able to. So just ignore the flag.
2943  */
2944  }
2945  else
2946  {
2947  /* ordinary table, fetch the tuple */
2948  Buffer buffer;
2949 
2950  tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
2951  if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
2952  false, NULL))
2953  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2954 
2955  /* successful, copy tuple */
2956  copyTuple = heap_copytuple(&tuple);
2957  ReleaseBuffer(buffer);
2958  }
2959 
2960  /* store tuple */
2961  EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
2962  }
2963  else
2964  {
2965  HeapTupleHeader td;
2966 
2967  Assert(erm->markType == ROW_MARK_COPY);
2968 
2969  /* fetch the whole-row Var for the relation */
2970  datum = ExecGetJunkAttribute(epqstate->origslot,
2971  aerm->wholeAttNo,
2972  &isNull);
2973  /* non-locked rels could be on the inside of outer joins */
2974  if (isNull)
2975  continue;
2976  td = DatumGetHeapTupleHeader(datum);
2977 
2978  /* build a temporary HeapTuple control structure */
2980  tuple.t_data = td;
2981  /* relation might be a foreign table, if so provide tableoid */
2982  tuple.t_tableOid = erm->relid;
2983  /* also copy t_ctid in case there's valid data there */
2984  tuple.t_self = td->t_ctid;
2985 
2986  /* copy and store tuple */
2987  EvalPlanQualSetTuple(epqstate, erm->rti,
2988  heap_copytuple(&tuple));
2989  }
2990  }
2991 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
void EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
Definition: execMain.c:2829
Relation relation
Definition: execnodes.h:537
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1876
#define DatumGetObjectId(X)
Definition: postgres.h:506
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:576
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:974
ItemPointerData * ItemPointer
Definition: itemptr.h:49
ExecRowMark * rowmark
Definition: execnodes.h:564
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:921
uint32 t_len
Definition: htup.h:64
Index rti
Definition: execnodes.h:539
AttrNumber wholeAttNo
Definition: execnodes.h:567
Index prti
Definition: execnodes.h:540
#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:919
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define SnapshotAny
Definition: tqual.h:28
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
RowMarkType markType
Definition: execnodes.h:542
AttrNumber toidAttNo
Definition: execnodes.h:566
#define DatumGetPointer(X)
Definition: postgres.h:555
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:917
int Buffer
Definition: buf.h:23
AttrNumber ctidAttNo
Definition: execnodes.h:565
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 2849 of file execMain.c.

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

2850 {
2851  EState *estate = epqstate->estate;
2852 
2853  Assert(rti > 0);
2854 
2855  return estate->es_epqTuple[rti - 1];
2856 }
HeapTuple * es_epqTuple
Definition: execnodes.h:507
#define Assert(condition)
Definition: c.h:670
EState * estate
Definition: execnodes.h:917

◆ EvalPlanQualInit()

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

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

2796 {
2797  /* Mark the EPQ state inactive */
2798  epqstate->estate = NULL;
2799  epqstate->planstate = NULL;
2800  epqstate->origslot = NULL;
2801  /* ... and remember data that EvalPlanQualBegin will need */
2802  epqstate->plan = subplan;
2803  epqstate->arowMarks = auxrowmarks;
2804  epqstate->epqParam = epqParam;
2805 }
PlanState * planstate
Definition: execnodes.h:918
List * arowMarks
Definition: execnodes.h:921
TupleTableSlot * origslot
Definition: execnodes.h:919
Plan * plan
Definition: execnodes.h:920
int epqParam
Definition: execnodes.h:922
EState * estate
Definition: execnodes.h:917

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 2999 of file execMain.c.

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

Referenced by EvalPlanQual(), and ExecLockRows().

3000 {
3001  MemoryContext oldcontext;
3002  TupleTableSlot *slot;
3003 
3004  oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
3005  slot = ExecProcNode(epqstate->planstate);
3006  MemoryContextSwitchTo(oldcontext);
3007 
3008  return slot;
3009 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:918
MemoryContext es_query_cxt
Definition: execnodes.h:472
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:236
EState * estate
Definition: execnodes.h:917

◆ EvalPlanQualSetPlan()

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

Definition at line 2813 of file execMain.c.

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

Referenced by ExecInitModifyTable(), and ExecModifyTable().

2814 {
2815  /* If we have a live EPQ query, shut it down */
2816  EvalPlanQualEnd(epqstate);
2817  /* And set/change the plan pointer */
2818  epqstate->plan = subplan;
2819  /* The rowmarks depend on the plan, too */
2820  epqstate->arowMarks = auxrowmarks;
2821 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3208
List * arowMarks
Definition: execnodes.h:921
Plan * plan
Definition: execnodes.h:920

◆ EvalPlanQualSetTuple()

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

Definition at line 2829 of file execMain.c.

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

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

2830 {
2831  EState *estate = epqstate->estate;
2832 
2833  Assert(rti > 0);
2834 
2835  /*
2836  * free old test tuple, if any, and store new tuple where relation's scan
2837  * node will see it
2838  */
2839  if (estate->es_epqTuple[rti - 1] != NULL)
2840  heap_freetuple(estate->es_epqTuple[rti - 1]);
2841  estate->es_epqTuple[rti - 1] = tuple;
2842  estate->es_epqTupleSet[rti - 1] = true;
2843 }
HeapTuple * es_epqTuple
Definition: execnodes.h:507
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define Assert(condition)
Definition: c.h:670
bool * es_epqTupleSet
Definition: execnodes.h:508
EState * estate
Definition: execnodes.h:917

◆ EvalPlanQualStart()

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

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

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

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

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

2408 {
2409  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2410  char resname[32];
2411 
2412  aerm->rowmark = erm;
2413 
2414  /* Look up the resjunk columns associated with this rowmark */
2415  if (erm->markType != ROW_MARK_COPY)
2416  {
2417  /* need ctid for all methods other than COPY */
2418  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2419  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2420  resname);
2421  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2422  elog(ERROR, "could not find junk %s column", resname);
2423  }
2424  else
2425  {
2426  /* need wholerow if COPY */
2427  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2428  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2429  resname);
2430  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2431  elog(ERROR, "could not find junk %s column", resname);
2432  }
2433 
2434  /* if child rel, need tableoid */
2435  if (erm->rti != erm->prti)
2436  {
2437  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2438  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2439  resname);
2440  if (!AttributeNumberIsValid(aerm->toidAttNo))
2441  elog(ERROR, "could not find junk %s column", resname);
2442  }
2443 
2444  return aerm;
2445 }
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:564
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:539
AttrNumber wholeAttNo
Definition: execnodes.h:567
Index prti
Definition: execnodes.h:540
Index rowmarkId
Definition: execnodes.h:541
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void * palloc0(Size size)
Definition: mcxt.c:877
RowMarkType markType
Definition: execnodes.h:542
AttrNumber toidAttNo
Definition: execnodes.h:566
#define elog
Definition: elog.h:219
AttrNumber ctidAttNo
Definition: execnodes.h:565

◆ ExecBuildSlotValueDescription()

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

Definition at line 2220 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(), ExecPartitionCheck(), and ExecWithCheckOptions().

2225 {
2227  StringInfoData collist;
2228  bool write_comma = false;
2229  bool write_comma_collist = false;
2230  int i;
2231  AclResult aclresult;
2232  bool table_perm = false;
2233  bool any_perm = false;
2234 
2235  /*
2236  * Check if RLS is enabled and should be active for the relation; if so,
2237  * then don't return anything. Otherwise, go through normal permission
2238  * checks.
2239  */
2240  if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2241  return NULL;
2242 
2243  initStringInfo(&buf);
2244 
2245  appendStringInfoChar(&buf, '(');
2246 
2247  /*
2248  * Check if the user has permissions to see the row. Table-level SELECT
2249  * allows access to all columns. If the user does not have table-level
2250  * SELECT then we check each column and include those the user has SELECT
2251  * rights on. Additionally, we always include columns the user provided
2252  * data for.
2253  */
2254  aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2255  if (aclresult != ACLCHECK_OK)
2256  {
2257  /* Set up the buffer for the column list */
2258  initStringInfo(&collist);
2259  appendStringInfoChar(&collist, '(');
2260  }
2261  else
2262  table_perm = any_perm = true;
2263 
2264  /* Make sure the tuple is fully deconstructed */
2265  slot_getallattrs(slot);
2266 
2267  for (i = 0; i < tupdesc->natts; i++)
2268  {
2269  bool column_perm = false;
2270  char *val;
2271  int vallen;
2272  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2273 
2274  /* ignore dropped columns */
2275  if (att->attisdropped)
2276  continue;
2277 
2278  if (!table_perm)
2279  {
2280  /*
2281  * No table-level SELECT, so need to make sure they either have
2282  * SELECT rights on the column or that they have provided the data
2283  * for the column. If not, omit this column from the error
2284  * message.
2285  */
2286  aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2287  GetUserId(), ACL_SELECT);
2289  modifiedCols) || aclresult == ACLCHECK_OK)
2290  {
2291  column_perm = any_perm = true;
2292 
2293  if (write_comma_collist)
2294  appendStringInfoString(&collist, ", ");
2295  else
2296  write_comma_collist = true;
2297 
2298  appendStringInfoString(&collist, NameStr(att->attname));
2299  }
2300  }
2301 
2302  if (table_perm || column_perm)
2303  {
2304  if (slot->tts_isnull[i])
2305  val = "null";
2306  else
2307  {
2308  Oid foutoid;
2309  bool typisvarlena;
2310 
2311  getTypeOutputInfo(att->atttypid,
2312  &foutoid, &typisvarlena);
2313  val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2314  }
2315 
2316  if (write_comma)
2317  appendStringInfoString(&buf, ", ");
2318  else
2319  write_comma = true;
2320 
2321  /* truncate if needed */
2322  vallen = strlen(val);
2323  if (vallen <= maxfieldlen)
2324  appendStringInfoString(&buf, val);
2325  else
2326  {
2327  vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2328  appendBinaryStringInfo(&buf, val, vallen);
2329  appendStringInfoString(&buf, "...");
2330  }
2331  }
2332  }
2333 
2334  /* If we end up with zero columns being returned, then return NULL. */
2335  if (!any_perm)
2336  return NULL;
2337 
2338  appendStringInfoChar(&buf, ')');
2339 
2340  if (!table_perm)
2341  {
2342  appendStringInfoString(&collist, ") = ");
2343  appendStringInfoString(&collist, buf.data);
2344 
2345  return collist.data;
2346  }
2347 
2348  return buf.data;
2349 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2665
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4366
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:53
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4480
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1742
int i
#define NameStr(name)
Definition: c.h:547
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
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:4366
Oid GetUserId(void)
Definition: miscinit.c:284
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1009
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
AclMode requiredPerms
Definition: parsenodes.h:1059
unsigned int Oid
Definition: postgres_ext.h:31
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3680
uint32 AclMode
Definition: parsenodes.h:70
Bitmapset * selectedCols
Definition: parsenodes.h:1061
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:663
#define ACL_UPDATE
Definition: parsenodes.h:74
#define ACL_SELECT
Definition: parsenodes.h:73
Bitmapset * updatedCols
Definition: parsenodes.h:1063
#define ACL_INSERT
Definition: parsenodes.h:72
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4395
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:951
Bitmapset * insertedCols
Definition: parsenodes.h:1062
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:4366
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1009
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define ERROR
Definition: elog.h:43
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4395
#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 ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NO_PRIV, Assert, ExecCheckRTEPerms(), ExecutorCheckPerms_hook, get_rel_name(), 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 }
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
static bool ExecCheckRTEPerms(RangeTblEntry *rte)
Definition: execMain.c:599
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:75
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
RTEKind rtekind
Definition: parsenodes.h:951
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1745

◆ 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:254
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1769
Definition: nodes.h:512
AclMode requiredPerms
Definition: parsenodes.h:1059
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3118
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2046
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:236
RTEKind rtekind
Definition: parsenodes.h:951

◆ ExecCleanUpTriggerState()

void ExecCleanUpTriggerState ( EState estate)

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

1467 {
1468  ListCell *l;
1469 
1470  foreach(l, estate->es_trig_target_relations)
1471  {
1472  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1473 
1474  /* Close indices and then the relation itself */
1475  ExecCloseIndices(resultRelInfo);
1476  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1477  }
1478 }
Relation ri_RelationDesc
Definition: execnodes.h:355
#define heap_close(r, l)
Definition: heapam.h:97
#define NoLock
Definition: lockdefs.h:34
List * es_trig_target_relations
Definition: execnodes.h:460
#define lfirst(lc)
Definition: pg_list.h:106
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:224

◆ ExecConstraints()

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

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

1943 {
1944  Relation rel = resultRelInfo->ri_RelationDesc;
1945  TupleDesc tupdesc = RelationGetDescr(rel);
1946  TupleConstr *constr = tupdesc->constr;
1947  Bitmapset *modifiedCols;
1948  Bitmapset *insertedCols;
1949  Bitmapset *updatedCols;
1950 
1951  Assert(constr || resultRelInfo->ri_PartitionCheck);
1952 
1953  if (constr && constr->has_not_null)
1954  {
1955  int natts = tupdesc->natts;
1956  int attrChk;
1957 
1958  for (attrChk = 1; attrChk <= natts; attrChk++)
1959  {
1960  Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
1961 
1962  if (att->attnotnull && slot_attisnull(slot, attrChk))
1963  {
1964  char *val_desc;
1965  Relation orig_rel = rel;
1966  TupleDesc orig_tupdesc = RelationGetDescr(rel);
1967 
1968  /*
1969  * If the tuple has been routed, it's been converted to the
1970  * partition's rowtype, which might differ from the root
1971  * table's. We must convert it back to the root table's
1972  * rowtype so that val_desc shown error message matches the
1973  * input tuple.
1974  */
1975  if (resultRelInfo->ri_PartitionRoot)
1976  {
1977  HeapTuple tuple = ExecFetchSlotTuple(slot);
1978  TupleConversionMap *map;
1979 
1980  rel = resultRelInfo->ri_PartitionRoot;
1981  tupdesc = RelationGetDescr(rel);
1982  /* a reverse map */
1983  map = convert_tuples_by_name(orig_tupdesc, tupdesc,
1984  gettext_noop("could not convert row type"));
1985  if (map != NULL)
1986  {
1987  tuple = do_convert_tuple(tuple, map);
1988  ExecSetSlotDescriptor(slot, tupdesc);
1989  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
1990  }
1991  }
1992 
1993  insertedCols = GetInsertedColumns(resultRelInfo, estate);
1994  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
1995  modifiedCols = bms_union(insertedCols, updatedCols);
1997  slot,
1998  tupdesc,
1999  modifiedCols,
2000  64);
2001 
2002  ereport(ERROR,
2003  (errcode(ERRCODE_NOT_NULL_VIOLATION),
2004  errmsg("null value in column \"%s\" violates not-null constraint",
2005  NameStr(att->attname)),
2006  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2007  errtablecol(orig_rel, attrChk)));
2008  }
2009  }
2010  }
2011 
2012  if (constr && constr->num_check > 0)
2013  {
2014  const char *failed;
2015 
2016  if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2017  {
2018  char *val_desc;
2019  Relation orig_rel = rel;
2020 
2021  /* See the comment above. */
2022  if (resultRelInfo->ri_PartitionRoot)
2023  {
2024  HeapTuple tuple = ExecFetchSlotTuple(slot);
2025  TupleDesc old_tupdesc = RelationGetDescr(rel);
2026  TupleConversionMap *map;
2027 
2028  rel = resultRelInfo->ri_PartitionRoot;
2029  tupdesc = RelationGetDescr(rel);
2030  /* a reverse map */
2031  map = convert_tuples_by_name(old_tupdesc, tupdesc,
2032  gettext_noop("could not convert row type"));
2033  if (map != NULL)
2034  {
2035  tuple = do_convert_tuple(tuple, map);
2036  ExecSetSlotDescriptor(slot, tupdesc);
2037  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2038  }
2039  }
2040 
2041  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2042  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2043  modifiedCols = bms_union(insertedCols, updatedCols);
2045  slot,
2046  tupdesc,
2047  modifiedCols,
2048  64);
2049  ereport(ERROR,
2050  (errcode(ERRCODE_CHECK_VIOLATION),
2051  errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2052  RelationGetRelationName(orig_rel), failed),
2053  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2054  errtableconstraint(orig_rel, failed)));
2055  }
2056  }
2057 
2058  if (resultRelInfo->ri_PartitionCheck)
2059  ExecPartitionCheck(resultRelInfo, slot, estate);
2060 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
Relation ri_RelationDesc
Definition: execnodes.h:355
#define RelationGetDescr(relation)
Definition: rel.h:437
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
Relation ri_PartitionRoot
Definition: execnodes.h:415
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:981
int errcode(int sqlerrcode)
Definition: elog.c:575
int natts
Definition: tupdesc.h:79
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5312
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2220
int errdetail(const char *fmt,...)
Definition: elog.c:873
#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:247
List * ri_PartitionCheck
Definition: execnodes.h:409
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1790
bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1329
void ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1854
#define Assert(condition)
Definition: c.h:670
int errtablecol(Relation rel, int attnum)
Definition: relcache.c:5275
TupleConstr * constr
Definition: tupdesc.h:84
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:618
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:547
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 1513 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 ExecAssignResultTypeFromTL(), ExecInitGather(), ExecInitGatherMerge(), and tlist_matches_tupdesc().

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

◆ ExecEndPlan()

static void ExecEndPlan ( PlanState planstate,
EState estate 
)
static

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

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

◆ ExecFindRowMark()

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

Definition at line 2383 of file execMain.c.

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

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

2384 {
2385  ListCell *lc;
2386 
2387  foreach(lc, estate->es_rowMarks)
2388  {
2389  ExecRowMark *erm = (ExecRowMark *) lfirst(lc);
2390 
2391  if (erm->rti == rti)
2392  return erm;
2393  }
2394  if (!missing_ok)
2395  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2396  return NULL;
2397 }
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:539
#define lfirst(lc)
Definition: pg_list.h:106
List * es_rowMarks
Definition: execnodes.h:476
#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_leaf_result_relations, 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, 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  /* Third, search through the leaf result relations, if any */
1417  foreach(l, estate->es_leaf_result_relations)
1418  {
1419  rInfo = (ResultRelInfo *) lfirst(l);
1420  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1421  return rInfo;
1422  }
1423  /* Nope, but maybe we already made an extra ResultRelInfo for it */
1424  foreach(l, estate->es_trig_target_relations)
1425  {
1426  rInfo = (ResultRelInfo *) lfirst(l);
1427  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1428  return rInfo;
1429  }
1430  /* Nope, so we need a new one */
1431 
1432  /*
1433  * Open the target relation's relcache entry. We assume that an
1434  * appropriate lock is still held by the backend from whenever the trigger
1435  * event got queued, so we need take no new lock here. Also, we need not
1436  * recheck the relkind, so no need for CheckValidResultRel.
1437  */
1438  rel = heap_open(relid, NoLock);
1439 
1440  /*
1441  * Make the new entry in the right context.
1442  */
1443  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1444  rInfo = makeNode(ResultRelInfo);
1445  InitResultRelInfo(rInfo,
1446  rel,
1447  0, /* dummy rangetable index */
1448  NULL,
1449  estate->es_instrument);
1450  estate->es_trig_target_relations =
1451  lappend(estate->es_trig_target_relations, rInfo);
1452  MemoryContextSwitchTo(oldcontext);
1453 
1454  /*
1455  * Currently, we don't need any index information in ResultRelInfos used
1456  * only for triggers, so no need to call ExecOpenIndices.
1457  */
1458 
1459  return rInfo;
1460 }
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1306
Relation ri_RelationDesc
Definition: execnodes.h:355
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:472
#define NoLock
Definition: lockdefs.h:34
ResultRelInfo * es_result_relations
Definition: execnodes.h:442
int es_instrument
Definition: execnodes.h:482
List * es_leaf_result_relations
Definition: execnodes.h:457
List * lappend(List *list, void *datum)
Definition: list.c:128
int es_num_root_result_relations
Definition: execnodes.h:454
List * es_trig_target_relations
Definition: execnodes.h:460
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
int es_num_result_relations
Definition: execnodes.h:443
#define makeNode(_type_)
Definition: nodes.h:560
#define lfirst(lc)
Definition: pg_list.h:106
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:453
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ ExecPartitionCheck()

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

Definition at line 1854 of file execMain.c.

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

Referenced by ExecConstraints(), and ExecFindPartition().

1856 {
1857  Relation rel = resultRelInfo->ri_RelationDesc;
1858  TupleDesc tupdesc = RelationGetDescr(rel);
1859  Bitmapset *modifiedCols;
1860  Bitmapset *insertedCols;
1861  Bitmapset *updatedCols;
1862  ExprContext *econtext;
1863 
1864  /*
1865  * If first time through, build expression state tree for the partition
1866  * check expression. Keep it in the per-query memory context so they'll
1867  * survive throughout the query.
1868  */
1869  if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1870  {
1871  List *qual = resultRelInfo->ri_PartitionCheck;
1872 
1873  resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1874  }
1875 
1876  /*
1877  * We will use the EState's per-tuple context for evaluating constraint
1878  * expressions (creating it if it's not already there).
1879  */
1880  econtext = GetPerTupleExprContext(estate);
1881 
1882  /* Arrange for econtext's scan tuple to be the tuple under test */
1883  econtext->ecxt_scantuple = slot;
1884 
1885  /*
1886  * As in case of the catalogued constraints, we treat a NULL result as
1887  * success here, not a failure.
1888  */
1889  if (!ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext))
1890  {
1891  char *val_desc;
1892  Relation orig_rel = rel;
1893 
1894  /* See the comment above. */
1895  if (resultRelInfo->ri_PartitionRoot)
1896  {
1897  HeapTuple tuple = ExecFetchSlotTuple(slot);
1898  TupleDesc old_tupdesc = RelationGetDescr(rel);
1899  TupleConversionMap *map;
1900 
1901  rel = resultRelInfo->ri_PartitionRoot;
1902  tupdesc = RelationGetDescr(rel);
1903  /* a reverse map */
1904  map = convert_tuples_by_name(old_tupdesc, tupdesc,
1905  gettext_noop("could not convert row type"));
1906  if (map != NULL)
1907  {
1908  tuple = do_convert_tuple(tuple, map);
1909  ExecSetSlotDescriptor(slot, tupdesc);
1910  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
1911  }
1912  }
1913 
1914  insertedCols = GetInsertedColumns(resultRelInfo, estate);
1915  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
1916  modifiedCols = bms_union(insertedCols, updatedCols);
1918  slot,
1919  tupdesc,
1920  modifiedCols,
1921  64);
1922  ereport(ERROR,
1923  (errcode(ERRCODE_CHECK_VIOLATION),
1924  errmsg("new row for relation \"%s\" violates partition constraint",
1925  RelationGetRelationName(orig_rel)),
1926  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
1927  }
1928 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
Relation ri_RelationDesc
Definition: execnodes.h:355
#define RelationGetDescr(relation)
Definition: rel.h:437
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:488
Relation ri_PartitionRoot
Definition: execnodes.h:415
ExprState * ri_PartitionCheckExpr
Definition: execnodes.h:412
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:981
int errcode(int sqlerrcode)
Definition: elog.c:575
#define GetPerTupleExprContext(estate)
Definition: executor.h:467
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2220
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:247
List * ri_PartitionCheck
Definition: execnodes.h:409
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:198
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:618
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:544
Definition: pg_list.h:45
#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 1549 of file execMain.c.

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

Referenced by standard_ExecutorFinish().

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

◆ ExecRelCheck()

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

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

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

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2357 of file execMain.c.

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

Referenced by ExecBRUpdateTriggers(), and ExecOnConflictUpdate().

2358 {
2359  Bitmapset *keyCols;
2360  Bitmapset *updatedCols;
2361 
2362  /*
2363  * Compute lock mode to use. If columns that are part of the key have not
2364  * been modified, then we can use a weaker lock, allowing for better
2365  * concurrency.
2366  */
2367  updatedCols = GetUpdatedColumns(relinfo, estate);
2368  keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2370 
2371  if (bms_overlap(keyCols, updatedCols))
2372  return LockTupleExclusive;
2373 
2374  return LockTupleNoKeyExclusive;
2375 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
Relation ri_RelationDesc
Definition: execnodes.h:355
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:4862

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

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

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

2075 {
2076  Relation rel = resultRelInfo->ri_RelationDesc;
2077  TupleDesc tupdesc = RelationGetDescr(rel);
2078  ExprContext *econtext;
2079  ListCell *l1,
2080  *l2;
2081 
2082  /*
2083  * We will use the EState's per-tuple context for evaluating constraint
2084  * expressions (creating it if it's not already there).
2085  */
2086  econtext = GetPerTupleExprContext(estate);
2087 
2088  /* Arrange for econtext's scan tuple to be the tuple under test */
2089  econtext->ecxt_scantuple = slot;
2090 
2091  /* Check each of the constraints */
2092  forboth(l1, resultRelInfo->ri_WithCheckOptions,
2093  l2, resultRelInfo->ri_WithCheckOptionExprs)
2094  {
2095  WithCheckOption *wco = (WithCheckOption *) lfirst(l1);
2096  ExprState *wcoExpr = (ExprState *) lfirst(l2);
2097 
2098  /*
2099  * Skip any WCOs which are not the kind we are looking for at this
2100  * time.
2101  */
2102  if (wco->kind != kind)
2103  continue;
2104 
2105  /*
2106  * WITH CHECK OPTION checks are intended to ensure that the new tuple
2107  * is visible (in the case of a view) or that it passes the
2108  * 'with-check' policy (in the case of row security). If the qual
2109  * evaluates to NULL or FALSE, then the new tuple won't be included in
2110  * the view or doesn't pass the 'with-check' policy for the table.
2111  */
2112  if (!ExecQual(wcoExpr, econtext))
2113  {
2114  char *val_desc;
2115  Bitmapset *modifiedCols;
2116  Bitmapset *insertedCols;
2117  Bitmapset *updatedCols;
2118 
2119  switch (wco->kind)
2120  {
2121  /*
2122  * For WITH CHECK OPTIONs coming from views, we might be
2123  * able to provide the details on the row, depending on
2124  * the permissions on the relation (that is, if the user
2125  * could view it directly anyway). For RLS violations, we
2126  * don't include the data since we don't know if the user
2127  * should be able to view the tuple as that depends on the
2128  * USING policy.
2129  */
2130  case WCO_VIEW_CHECK:
2131  /* See the comment in ExecConstraints(). */
2132  if (resultRelInfo->ri_PartitionRoot)
2133  {
2134  HeapTuple tuple = ExecFetchSlotTuple(slot);
2135  TupleDesc old_tupdesc = RelationGetDescr(rel);
2136  TupleConversionMap *map;
2137 
2138  rel = resultRelInfo->ri_PartitionRoot;
2139  tupdesc = RelationGetDescr(rel);
2140  /* a reverse map */
2141  map = convert_tuples_by_name(old_tupdesc, tupdesc,
2142  gettext_noop("could not convert row type"));
2143  if (map != NULL)
2144  {
2145  tuple = do_convert_tuple(tuple, map);
2146  ExecSetSlotDescriptor(slot, tupdesc);
2147  ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2148  }
2149  }
2150 
2151  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2152  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2153  modifiedCols = bms_union(insertedCols, updatedCols);
2155  slot,
2156  tupdesc,
2157  modifiedCols,
2158  64);
2159 
2160  ereport(ERROR,
2161  (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),
2162  errmsg("new row violates check option for view \"%s\"",
2163  wco->relname),
2164  val_desc ? errdetail("Failing row contains %s.",
2165  val_desc) : 0));
2166  break;
2167  case WCO_RLS_INSERT_CHECK:
2168  case WCO_RLS_UPDATE_CHECK:
2169  if (wco->polname != NULL)
2170  ereport(ERROR,
2171  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2172  errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
2173  wco->polname, wco->relname)));
2174  else
2175  ereport(ERROR,
2176  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2177  errmsg("new row violates row-level security policy for table \"%s\"",
2178  wco->relname)));
2179  break;
2181  if (wco->polname != NULL)
2182  ereport(ERROR,
2183  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2184  errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2185  wco->polname, wco->relname)));
2186  else
2187  ereport(ERROR,
2188  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2189  errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
2190  wco->relname)));
2191  break;
2192  default:
2193  elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
2194  break;
2195  }
2196  }
2197  }
2198 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
Relation ri_RelationDesc
Definition: execnodes.h:355
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
#define RelationGetDescr(relation)
Definition: rel.h:437
Relation ri_PartitionRoot
Definition: execnodes.h:415
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:981
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:356
List * ri_WithCheckOptionExprs
Definition: execnodes.h:391
#define GetPerTupleExprContext(estate)
Definition: executor.h:467
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2220
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:247
List * ri_WithCheckOptions
Definition: execnodes.h:388
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:198
HeapTuple do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:354
HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:618
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));
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:507
JunkFilter * es_junkFilter
Definition: execnodes.h:436
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1306
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
RowMarkType markType
Definition: plannodes.h:1021
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:463
Relation relation
Definition: execnodes.h:537
#define AccessShareLock
Definition: lockdefs.h:36
PlannedStmt * es_plannedstmt
Definition: execnodes.h:433
bool ermActive
Definition: execnodes.h:545
Index prti
Definition: plannodes.h:1019
LockWaitPolicy waitPolicy
Definition: execnodes.h:544
#define EXEC_FLAG_WITH_NO_DATA
Definition: executor.h:65
LockClauseStrength strength
Definition: execnodes.h:543
List * es_range_table
Definition: execnodes.h:432
unsigned int Oid
Definition: postgres_ext.h:31
Index rowmarkId
Definition: plannodes.h:1020
LockWaitPolicy waitPolicy
Definition: plannodes.h:1024
static void CheckValidRowMarkRel(Relation rel, RowMarkType markType)
Definition: execMain.c:1241
struct Plan * planTree
Definition: plannodes.h:61
ItemPointerData curCtid
Definition: execnodes.h:546
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:539
void * ermExtra
Definition: execnodes.h:547
TupleDesc jf_cleanTupType
Definition: execnodes.h:334
ResultRelInfo * es_result_relations
Definition: execnodes.h:442
#define RowExclusiveLock
Definition: lockdefs.h:38
Index prti
Definition: execnodes.h:540
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:462
int es_instrument
Definition: execnodes.h:482
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:461
#define EXEC_FLAG_REWIND
Definition: executor.h:59
Index rowmarkId
Definition: execnodes.h:541
List * lappend(List *list, void *datum)
Definition: list.c:128
int es_num_root_result_relations
Definition: execnodes.h:454
TupleDesc tupDesc
Definition: execdesc.h:47
CmdType operation
Definition: execdesc.h:36
List * es_tupleTable
Definition: execnodes.h:474
#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:443
unsigned int Index
Definition: c.h:413
List * rowMarks
Definition: plannodes.h:86
Plan * plan
Definition: execnodes.h:850
List * subplans
Definition: plannodes.h:81
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * rewindPlanIDs
Definition: plannodes.h:84
RowMarkType markType
Definition: execnodes.h:542
LockClauseStrength strength
Definition: plannodes.h:1023
static int list_length(const List *l)
Definition: pg_list.h:89
bool * es_epqTupleSet
Definition: execnodes.h:508
List * es_subplanstates
Definition: execnodes.h:487
List * es_rowMarks
Definition: execnodes.h:476
List * rtable
Definition: plannodes.h:63
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:477
List * targetlist
Definition: plannodes.h:144
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
void * palloc(Size size)
Definition: mcxt.c:848
#define getrelid(rangeindex, rangetable)
Definition: parsetree.h:41
List * resultRelations
Definition: plannodes.h:66
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:453
int i
bool * es_epqScanDone
Definition: execnodes.h:509
bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
Definition: execMain.c:568
bool isParent
Definition: plannodes.h:1025
#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:420
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
CmdType
Definition: nodes.h:652
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:444

◆ 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:358
#define NIL
Definition: pg_list.h:69
JunkFilter * ri_junkFilter
Definition: execnodes.h:397
Definition: fmgr.h:56
Relation ri_RelationDesc
Definition: execnodes.h:355
Relation ri_PartitionRoot
Definition: execnodes.h:415
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:376
Instrumentation * InstrAlloc(int n, int instrument_options)
Definition: instrument.c:30
#define MemSet(start, val, len)
Definition: c.h:853
Form_pg_class rd_rel
Definition: rel.h:114
Index ri_RangeTableIndex
Definition: execnodes.h:352
NodeTag type
Definition: execnodes.h:349
TriggerDesc * trigdesc
Definition: rel.h:120
bool ri_usesFdwDirectModify
Definition: execnodes.h:385
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:373
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:400
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:379
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:394
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:367
int numtriggers
Definition: reltrigger.h:49
List * RelationGetPartitionQual(Relation rel)
Definition: partition.c:1494
void * palloc0(Size size)
Definition: mcxt.c:877
List * ri_PartitionCheck
Definition: execnodes.h:409
void * ri_FdwState
Definition: execnodes.h:382
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:1911
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:364
Definition: pg_list.h:45
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:361
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:370

◆ 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:431
Snapshot es_snapshot
Definition: execnodes.h:430
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
MemoryContext es_query_cxt
Definition: execnodes.h:472
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:483
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:670
static void ExecEndPlan(PlanState *planstate, EState *estate)
Definition: execMain.c:1595
int es_top_eflags
Definition: execnodes.h:481
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58

◆ 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:1549
EState * estate
Definition: execdesc.h:48
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:472
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:63
bool es_finished
Definition: execnodes.h:483
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:670
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:62
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4546
int es_top_eflags
Definition: execnodes.h:481
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58

◆ standard_ExecutorRun()

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

Definition at line 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:479
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:48
MemoryContext es_query_cxt
Definition: execnodes.h:472
#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:670
uint64 es_processed
Definition: execnodes.h:478
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
DestReceiver * dest
Definition: execdesc.h:41
int es_top_eflags
Definition: execnodes.h:481
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:58
CmdType
Definition: nodes.h:652
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:1673

◆ 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:439
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:431
Snapshot es_snapshot
Definition: execnodes.h:430
Snapshot snapshot
Definition: execdesc.h:39
int instrument_options
Definition: execdesc.h:44
const char * es_sourceText
Definition: execnodes.h:434
ParamExecData * es_param_exec_vals
Definition: execnodes.h:467
QueryEnvironment * queryEnv
Definition: execdesc.h:43
MemoryContext es_query_cxt
Definition: execnodes.h:472
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:482
EState * CreateExecutorState(void)
Definition: execUtils.c:81
QueryEnvironment * es_queryEnv
Definition: execnodes.h:469
CmdType operation
Definition: execdesc.h:36
static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
Definition: execMain.c:766
void * palloc0(Size size)
Definition: mcxt.c:877
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:4526
#define Assert(condition)
Definition: c.h:670
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:62
const char * sourceText
Definition: execdesc.h:38
int es_top_eflags
Definition: execnodes.h:481
ParamListInfo es_param_list_info
Definition: execnodes.h:466
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:58
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().