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

Go to the source code of this file.

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, 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, ResultRelInfo *partition_root_rri, int instrument_options)
 
ResultRelInfoExecGetTriggerResultRel (EState *estate, Oid relid)
 
void ExecCloseResultRelations (EState *estate)
 
void ExecCloseRangeTableRelations (EState *estate)
 
static const char * ExecRelCheck (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
bool ExecPartitionCheck (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
 
void ExecPartitionCheckEmitError (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
void ExecConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
void ExecWithCheckOptions (WCOKind kind, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
LockTupleMode ExecUpdateLockMode (EState *estate, ResultRelInfo *relinfo)
 
ExecRowMarkExecFindRowMark (EState *estate, Index rti, bool missing_ok)
 
ExecAuxRowMarkExecBuildAuxRowMark (ExecRowMark *erm, List *targetlist)
 
TupleTableSlotEvalPlanQual (EPQState *epqstate, Relation relation, Index rti, TupleTableSlot *inputslot)
 
void EvalPlanQualInit (EPQState *epqstate, EState *parentestate, Plan *subplan, List *auxrowmarks, int epqParam)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
TupleTableSlotEvalPlanQualSlot (EPQState *epqstate, Relation relation, Index rti)
 
bool EvalPlanQualFetchRowMark (EPQState *epqstate, Index rti, TupleTableSlot *slot)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate)
 
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
 

Function Documentation

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation 
)

Definition at line 992 of file execMain.c.

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

Referenced by CopyFrom(), ExecFindPartition(), ExecGetJunkAttribute(), ExecInitModifyTable(), and ExecInitPartitionInfo().

993 {
994  Relation resultRel = resultRelInfo->ri_RelationDesc;
995  TriggerDesc *trigDesc = resultRel->trigdesc;
996  FdwRoutine *fdwroutine;
997 
998  switch (resultRel->rd_rel->relkind)
999  {
1000  case RELKIND_RELATION:
1001  case RELKIND_PARTITIONED_TABLE:
1002  CheckCmdReplicaIdentity(resultRel, operation);
1003  break;
1004  case RELKIND_SEQUENCE:
1005  ereport(ERROR,
1006  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1007  errmsg("cannot change sequence \"%s\"",
1008  RelationGetRelationName(resultRel))));
1009  break;
1010  case RELKIND_TOASTVALUE:
1011  ereport(ERROR,
1012  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1013  errmsg("cannot change TOAST relation \"%s\"",
1014  RelationGetRelationName(resultRel))));
1015  break;
1016  case RELKIND_VIEW:
1017 
1018  /*
1019  * Okay only if there's a suitable INSTEAD OF trigger. Messages
1020  * here should match rewriteHandler.c's rewriteTargetView and
1021  * RewriteQuery, except that we omit errdetail because we haven't
1022  * got the information handy (and given that we really shouldn't
1023  * get here anyway, it's not worth great exertion to get).
1024  */
1025  switch (operation)
1026  {
1027  case CMD_INSERT:
1028  if (!trigDesc || !trigDesc->trig_insert_instead_row)
1029  ereport(ERROR,
1030  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1031  errmsg("cannot insert into view \"%s\"",
1032  RelationGetRelationName(resultRel)),
1033  errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
1034  break;
1035  case CMD_UPDATE:
1036  if (!trigDesc || !trigDesc->trig_update_instead_row)
1037  ereport(ERROR,
1038  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1039  errmsg("cannot update view \"%s\"",
1040  RelationGetRelationName(resultRel)),
1041  errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
1042  break;
1043  case CMD_DELETE:
1044  if (!trigDesc || !trigDesc->trig_delete_instead_row)
1045  ereport(ERROR,
1046  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1047  errmsg("cannot delete from view \"%s\"",
1048  RelationGetRelationName(resultRel)),
1049  errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
1050  break;
1051  default:
1052  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1053  break;
1054  }
1055  break;
1056  case RELKIND_MATVIEW:
1058  ereport(ERROR,
1059  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1060  errmsg("cannot change materialized view \"%s\"",
1061  RelationGetRelationName(resultRel))));
1062  break;
1063  case RELKIND_FOREIGN_TABLE:
1064  /* Okay only if the FDW supports it */
1065  fdwroutine = resultRelInfo->ri_FdwRoutine;
1066  switch (operation)
1067  {
1068  case CMD_INSERT:
1069  if (fdwroutine->ExecForeignInsert == NULL)
1070  ereport(ERROR,
1071  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1072  errmsg("cannot insert into foreign table \"%s\"",
1073  RelationGetRelationName(resultRel))));
1074  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1075  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1076  ereport(ERROR,
1077  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1078  errmsg("foreign table \"%s\" does not allow inserts",
1079  RelationGetRelationName(resultRel))));
1080  break;
1081  case CMD_UPDATE:
1082  if (fdwroutine->ExecForeignUpdate == NULL)
1083  ereport(ERROR,
1084  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1085  errmsg("cannot update foreign table \"%s\"",
1086  RelationGetRelationName(resultRel))));
1087  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1088  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1089  ereport(ERROR,
1090  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1091  errmsg("foreign table \"%s\" does not allow updates",
1092  RelationGetRelationName(resultRel))));
1093  break;
1094  case CMD_DELETE:
1095  if (fdwroutine->ExecForeignDelete == NULL)
1096  ereport(ERROR,
1097  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1098  errmsg("cannot delete from foreign table \"%s\"",
1099  RelationGetRelationName(resultRel))));
1100  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1101  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1102  ereport(ERROR,
1103  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1104  errmsg("foreign table \"%s\" does not allow deletes",
1105  RelationGetRelationName(resultRel))));
1106  break;
1107  default:
1108  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1109  break;
1110  }
1111  break;
1112  default:
1113  ereport(ERROR,
1114  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1115  errmsg("cannot change relation \"%s\"",
1116  RelationGetRelationName(resultRel))));
1117  break;
1118  }
1119 }
ExecForeignDelete_function ExecForeignDelete
Definition: fdwapi.h:236
Relation ri_RelationDesc
Definition: execnodes.h:411
int errhint(const char *fmt,...)
Definition: elog.c:1156
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition: matview.c:919
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:232
int errcode(int sqlerrcode)
Definition: elog.c:698
Form_pg_class rd_rel
Definition: rel.h:109
bool trig_insert_instead_row
Definition: reltrigger.h:58
#define ERROR
Definition: elog.h:46
TriggerDesc * trigdesc
Definition: rel.h:115
#define RelationGetRelationName(relation)
Definition: rel.h:503
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:455
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
bool trig_update_instead_row
Definition: reltrigger.h:63
bool trig_delete_instead_row
Definition: reltrigger.h:68
#define ereport(elevel,...)
Definition: elog.h:157
ExecForeignUpdate_function ExecForeignUpdate
Definition: fdwapi.h:235
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
IsForeignRelUpdatable_function IsForeignRelUpdatable
Definition: fdwapi.h:240

◆ CheckValidRowMarkRel()

static void CheckValidRowMarkRel ( Relation  rel,
RowMarkType  markType 
)
static

Definition at line 1128 of file execMain.c.

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

Referenced by InitPlan().

1129 {
1130  FdwRoutine *fdwroutine;
1131 
1132  switch (rel->rd_rel->relkind)
1133  {
1134  case RELKIND_RELATION:
1135  case RELKIND_PARTITIONED_TABLE:
1136  /* OK */
1137  break;
1138  case RELKIND_SEQUENCE:
1139  /* Must disallow this because we don't vacuum sequences */
1140  ereport(ERROR,
1141  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1142  errmsg("cannot lock rows in sequence \"%s\"",
1143  RelationGetRelationName(rel))));
1144  break;
1145  case RELKIND_TOASTVALUE:
1146  /* We could allow this, but there seems no good reason to */
1147  ereport(ERROR,
1148  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1149  errmsg("cannot lock rows in TOAST relation \"%s\"",
1150  RelationGetRelationName(rel))));
1151  break;
1152  case RELKIND_VIEW:
1153  /* Should not get here; planner should have expanded the view */
1154  ereport(ERROR,
1155  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1156  errmsg("cannot lock rows in view \"%s\"",
1157  RelationGetRelationName(rel))));
1158  break;
1159  case RELKIND_MATVIEW:
1160  /* Allow referencing a matview, but not actual locking clauses */
1161  if (markType != ROW_MARK_REFERENCE)
1162  ereport(ERROR,
1163  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1164  errmsg("cannot lock rows in materialized view \"%s\"",
1165  RelationGetRelationName(rel))));
1166  break;
1167  case RELKIND_FOREIGN_TABLE:
1168  /* Okay only if the FDW supports it */
1169  fdwroutine = GetFdwRoutineForRelation(rel, false);
1170  if (fdwroutine->RefetchForeignRow == NULL)
1171  ereport(ERROR,
1172  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1173  errmsg("cannot lock rows in foreign table \"%s\"",
1174  RelationGetRelationName(rel))));
1175  break;
1176  default:
1177  ereport(ERROR,
1178  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1179  errmsg("cannot lock rows in relation \"%s\"",
1180  RelationGetRelationName(rel))));
1181  break;
1182  }
1183 }
int errcode(int sqlerrcode)
Definition: elog.c:698
Form_pg_class rd_rel
Definition: rel.h:109
#define ERROR
Definition: elog.h:46
#define RelationGetRelationName(relation)
Definition: rel.h:503
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:427
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:248

◆ EvalPlanQual()

TupleTableSlot* EvalPlanQual ( EPQState epqstate,
Relation  relation,
Index  rti,
TupleTableSlot inputslot 
)

Definition at line 2359 of file execMain.c.

References Assert, EvalPlanQualBegin(), EvalPlanQualNext(), EvalPlanQualSlot(), ExecClearTuple(), ExecCopySlot(), ExecMaterializeSlot(), and TupIsNull.

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

2361 {
2362  TupleTableSlot *slot;
2363  TupleTableSlot *testslot;
2364 
2365  Assert(rti > 0);
2366 
2367  /*
2368  * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2369  */
2370  EvalPlanQualBegin(epqstate);
2371 
2372  /*
2373  * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
2374  * an unnecessary copy.
2375  */
2376  testslot = EvalPlanQualSlot(epqstate, relation, rti);
2377  if (testslot != inputslot)
2378  ExecCopySlot(testslot, inputslot);
2379 
2380  /*
2381  * Run the EPQ query. We assume it will return at most one tuple.
2382  */
2383  slot = EvalPlanQualNext(epqstate);
2384 
2385  /*
2386  * If we got a tuple, force the slot to materialize the tuple so that it
2387  * is not dependent on any local state in the EPQ query (in particular,
2388  * it's highly likely that the slot contains references to any pass-by-ref
2389  * datums that may be present in copyTuple). As with the next step, this
2390  * is to guard against early re-use of the EPQ query.
2391  */
2392  if (!TupIsNull(slot))
2393  ExecMaterializeSlot(slot);
2394 
2395  /*
2396  * Clear out the test tuple. This is needed in case the EPQ query is
2397  * re-used to test a tuple for a different relation. (Not clear that can
2398  * really happen, but let's be safe.)
2399  */
2400  ExecClearTuple(testslot);
2401 
2402  return slot;
2403 }
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:475
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition: execMain.c:2606
TupleTableSlot * EvalPlanQualSlot(EPQState *epqstate, Relation relation, Index rti)
Definition: execMain.c:2469
#define TupIsNull(slot)
Definition: tuptable.h:292
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:443
#define Assert(condition)
Definition: c.h:804
void EvalPlanQualBegin(EPQState *epqstate)
Definition: execMain.c:2622

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2622 of file execMain.c.

References bms_add_member(), PlanState::chgParam, EPQState::epqParam, EState::es_param_exec_vals, EState::es_plannedstmt, EState::es_range_table_size, EvalPlanQualStart(), ExecSetParamPlanMulti(), Plan::extParam, GetPerTupleExprContext, i, ParamExecData::isnull, list_length(), MemSet, NIL, PlannedStmt::paramExecTypes, EPQState::parentestate, PlanState::plan, EPQState::plan, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_done, and ParamExecData::value.

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

2623 {
2624  EState *parentestate = epqstate->parentestate;
2625  EState *recheckestate = epqstate->recheckestate;
2626 
2627  if (recheckestate == NULL)
2628  {
2629  /* First time through, so create a child EState */
2630  EvalPlanQualStart(epqstate, epqstate->plan);
2631  }
2632  else
2633  {
2634  /*
2635  * We already have a suitable child EPQ tree, so just reset it.
2636  */
2637  Index rtsize = parentestate->es_range_table_size;
2638  PlanState *rcplanstate = epqstate->recheckplanstate;
2639 
2640  MemSet(epqstate->relsubs_done, 0, rtsize * sizeof(bool));
2641 
2642  /* Recopy current values of parent parameters */
2643  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2644  {
2645  int i;
2646 
2647  /*
2648  * Force evaluation of any InitPlan outputs that could be needed
2649  * by the subplan, just in case they got reset since
2650  * EvalPlanQualStart (see comments therein).
2651  */
2652  ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2653  GetPerTupleExprContext(parentestate));
2654 
2655  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2656 
2657  while (--i >= 0)
2658  {
2659  /* copy value if any, but not execPlan link */
2660  recheckestate->es_param_exec_vals[i].value =
2661  parentestate->es_param_exec_vals[i].value;
2662  recheckestate->es_param_exec_vals[i].isnull =
2663  parentestate->es_param_exec_vals[i].isnull;
2664  }
2665  }
2666 
2667  /*
2668  * Mark child plan tree as needing rescan at all scan nodes. The
2669  * first ExecProcNode will take care of actually doing the rescan.
2670  */
2671  rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2672  epqstate->epqParam);
2673  }
2674 }
List * paramExecTypes
Definition: plannodes.h:84
#define NIL
Definition: pg_list.h:65
void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext)
Definition: nodeSubplan.c:1253
PlannedStmt * es_plannedstmt
Definition: execnodes.h:564
#define MemSet(start, val, len)
Definition: c.h:1008
EState * parentestate
Definition: execnodes.h:1099
#define GetPerTupleExprContext(estate)
Definition: executor.h:532
ParamExecData * es_param_exec_vals
Definition: execnodes.h:593
EState * recheckestate
Definition: execnodes.h:1129
bool isnull
Definition: params.h:150
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition: execMain.c:2683
bool * relsubs_done
Definition: execnodes.h:1142
Bitmapset * chgParam
Definition: execnodes.h:996
Plan * plan
Definition: execnodes.h:1115
unsigned int Index
Definition: c.h:549
Plan * plan
Definition: execnodes.h:964
static int list_length(const List *l)
Definition: pg_list.h:149
Bitmapset * extParam
Definition: plannodes.h:159
Index es_range_table_size
Definition: execnodes.h:559
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
int i
Datum value
Definition: params.h:149
int epqParam
Definition: execnodes.h:1100
PlanState * recheckplanstate
Definition: execnodes.h:1144

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2834 of file execMain.c.

References EState::es_query_cxt, EState::es_range_table_size, EState::es_subplanstates, EState::es_tupleTable, ExecCloseResultRelations(), ExecEndNode(), ExecResetTupleTable(), FreeExecutorState(), lfirst, MemoryContextSwitchTo(), NIL, EPQState::origslot, EPQState::parentestate, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::relsubs_slot, and EPQState::tuple_table.

Referenced by apply_handle_delete_internal(), apply_handle_tuple_routing(), apply_handle_update_internal(), EvalPlanQualSetPlan(), ExecEndLockRows(), and ExecEndModifyTable().

2835 {
2836  EState *estate = epqstate->recheckestate;
2837  Index rtsize;
2838  MemoryContext oldcontext;
2839  ListCell *l;
2840 
2841  rtsize = epqstate->parentestate->es_range_table_size;
2842 
2843  /*
2844  * We may have a tuple table, even if EPQ wasn't started, because we allow
2845  * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
2846  */
2847  if (epqstate->tuple_table != NIL)
2848  {
2849  memset(epqstate->relsubs_slot, 0,
2850  rtsize * sizeof(TupleTableSlot *));
2851  ExecResetTupleTable(epqstate->tuple_table, true);
2852  epqstate->tuple_table = NIL;
2853  }
2854 
2855  /* EPQ wasn't started, nothing further to do */
2856  if (estate == NULL)
2857  return;
2858 
2859  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
2860 
2861  ExecEndNode(epqstate->recheckplanstate);
2862 
2863  foreach(l, estate->es_subplanstates)
2864  {
2865  PlanState *subplanstate = (PlanState *) lfirst(l);
2866 
2867  ExecEndNode(subplanstate);
2868  }
2869 
2870  /* throw away the per-estate tuple table, some node may have used it */
2871  ExecResetTupleTable(estate->es_tupleTable, false);
2872 
2873  /* Close any result and trigger target relations attached to this EState */
2874  ExecCloseResultRelations(estate);
2875 
2876  MemoryContextSwitchTo(oldcontext);
2877 
2878  FreeExecutorState(estate);
2879 
2880  /* Mark EPQState idle */
2881  epqstate->origslot = NULL;
2882  epqstate->recheckestate = NULL;
2883  epqstate->recheckplanstate = NULL;
2884  epqstate->relsubs_rowmark = NULL;
2885  epqstate->relsubs_done = NULL;
2886 }
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1108
#define NIL
Definition: pg_list.h:65
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:555
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1439
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
EState * parentestate
Definition: execnodes.h:1099
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
MemoryContext es_query_cxt
Definition: execnodes.h:598
EState * recheckestate
Definition: execnodes.h:1129
List * tuple_table
Definition: execnodes.h:1107
bool * relsubs_done
Definition: execnodes.h:1142
TupleTableSlot * origslot
Definition: execnodes.h:1124
List * es_tupleTable
Definition: execnodes.h:600
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1191
unsigned int Index
Definition: c.h:549
#define lfirst(lc)
Definition: pg_list.h:169
Index es_range_table_size
Definition: execnodes.h:559
List * es_subplanstates
Definition: execnodes.h:610
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1136
PlanState * recheckplanstate
Definition: execnodes.h:1144

◆ EvalPlanQualFetchRowMark()

bool EvalPlanQualFetchRowMark ( EPQState epqstate,
Index  rti,
TupleTableSlot slot 
)

Definition at line 2497 of file execMain.c.

References Assert, ExecAuxRowMark::ctidAttNo, DatumGetObjectId, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, ExecGetJunkAttribute(), ExecStoreHeapTupleDatum(), GetFdwRoutineForRelation(), ExecRowMark::markType, OidIsValid, EPQState::origslot, ExecRowMark::prti, RelationData::rd_rel, EPQState::recheckestate, FdwRoutine::RefetchForeignRow, ExecRowMark::relation, RelationGetRelationName, ExecRowMark::relid, EPQState::relsubs_rowmark, ROW_MARK_COPY, ROW_MARK_REFERENCE, ExecAuxRowMark::rowmark, RowMarkRequiresRowShareLock, ExecRowMark::rti, SnapshotAny, table_tuple_fetch_row_version(), ExecAuxRowMark::toidAttNo, TupIsNull, and ExecAuxRowMark::wholeAttNo.

Referenced by ExecScanFetch().

2498 {
2499  ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1];
2500  ExecRowMark *erm = earm->rowmark;
2501  Datum datum;
2502  bool isNull;
2503 
2504  Assert(earm != NULL);
2505  Assert(epqstate->origslot != NULL);
2506 
2508  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2509 
2510  /* if child rel, must check whether it produced this row */
2511  if (erm->rti != erm->prti)
2512  {
2513  Oid tableoid;
2514 
2515  datum = ExecGetJunkAttribute(epqstate->origslot,
2516  earm->toidAttNo,
2517  &isNull);
2518  /* non-locked rels could be on the inside of outer joins */
2519  if (isNull)
2520  return false;
2521 
2522  tableoid = DatumGetObjectId(datum);
2523 
2524  Assert(OidIsValid(erm->relid));
2525  if (tableoid != erm->relid)
2526  {
2527  /* this child is inactive right now */
2528  return false;
2529  }
2530  }
2531 
2532  if (erm->markType == ROW_MARK_REFERENCE)
2533  {
2534  Assert(erm->relation != NULL);
2535 
2536  /* fetch the tuple's ctid */
2537  datum = ExecGetJunkAttribute(epqstate->origslot,
2538  earm->ctidAttNo,
2539  &isNull);
2540  /* non-locked rels could be on the inside of outer joins */
2541  if (isNull)
2542  return false;
2543 
2544  /* fetch requests on foreign tables must be passed to their FDW */
2545  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2546  {
2547  FdwRoutine *fdwroutine;
2548  bool updated = false;
2549 
2550  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2551  /* this should have been checked already, but let's be safe */
2552  if (fdwroutine->RefetchForeignRow == NULL)
2553  ereport(ERROR,
2554  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2555  errmsg("cannot lock rows in foreign table \"%s\"",
2557 
2558  fdwroutine->RefetchForeignRow(epqstate->recheckestate,
2559  erm,
2560  datum,
2561  slot,
2562  &updated);
2563  if (TupIsNull(slot))
2564  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2565 
2566  /*
2567  * Ideally we'd insist on updated == false here, but that assumes
2568  * that FDWs can track that exactly, which they might not be able
2569  * to. So just ignore the flag.
2570  */
2571  return true;
2572  }
2573  else
2574  {
2575  /* ordinary table, fetch the tuple */
2577  (ItemPointer) DatumGetPointer(datum),
2578  SnapshotAny, slot))
2579  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2580  return true;
2581  }
2582  }
2583  else
2584  {
2585  Assert(erm->markType == ROW_MARK_COPY);
2586 
2587  /* fetch the whole-row Var for the relation */
2588  datum = ExecGetJunkAttribute(epqstate->origslot,
2589  earm->wholeAttNo,
2590  &isNull);
2591  /* non-locked rels could be on the inside of outer joins */
2592  if (isNull)
2593  return false;
2594 
2595  ExecStoreHeapTupleDatum(datum, slot);
2596  return true;
2597  }
2598 }
Relation relation
Definition: execnodes.h:670
#define DatumGetObjectId(X)
Definition: postgres.h:544
int errcode(int sqlerrcode)
Definition: elog.c:698
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:1073
ExecRowMark * rowmark
Definition: execnodes.h:694
#define ERROR
Definition: elog.h:46
EState * recheckestate
Definition: execnodes.h:1129
Index rti
Definition: execnodes.h:672
AttrNumber wholeAttNo
Definition: execnodes.h:697
Index prti
Definition: execnodes.h:673
#define RelationGetRelationName(relation)
Definition: rel.h:503
#define TupIsNull(slot)
Definition: tuptable.h:292
TupleTableSlot * origslot
Definition: execnodes.h:1124
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
Definition: execTuples.c:1606
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
Definition: tableam.h:1257
static Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: executor.h:178
uintptr_t Datum
Definition: postgres.h:411
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
RowMarkType markType
Definition: execnodes.h:675
AttrNumber toidAttNo
Definition: execnodes.h:696
#define SnapshotAny
Definition: snapmgr.h:67
#define DatumGetPointer(X)
Definition: postgres.h:593
int errmsg(const char *fmt,...)
Definition: elog.c:909
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:427
#define elog(elevel,...)
Definition: elog.h:232
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1136
AttrNumber ctidAttNo
Definition: execnodes.h:695
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:248

◆ EvalPlanQualInit()

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

Definition at line 2413 of file execMain.c.

References EPQState::arowMarks, EPQState::epqParam, EState::es_range_table_size, NIL, EPQState::origslot, palloc0(), EPQState::parentestate, EPQState::plan, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::relsubs_slot, ExprEvalStep::subplan, and EPQState::tuple_table.

Referenced by apply_handle_delete_internal(), apply_handle_tuple_routing(), apply_handle_update_internal(), ExecGetJunkAttribute(), ExecInitLockRows(), and ExecInitModifyTable().

2415 {
2416  Index rtsize = parentestate->es_range_table_size;
2417 
2418  /* initialize data not changing over EPQState's lifetime */
2419  epqstate->parentestate = parentestate;
2420  epqstate->epqParam = epqParam;
2421 
2422  /*
2423  * Allocate space to reference a slot for each potential rti - do so now
2424  * rather than in EvalPlanQualBegin(), as done for other dynamically
2425  * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2426  * that *may* need EPQ later, without forcing the overhead of
2427  * EvalPlanQualBegin().
2428  */
2429  epqstate->tuple_table = NIL;
2430  epqstate->relsubs_slot = (TupleTableSlot **)
2431  palloc0(rtsize * sizeof(TupleTableSlot *));
2432 
2433  /* ... and remember data that EvalPlanQualBegin will need */
2434  epqstate->plan = subplan;
2435  epqstate->arowMarks = auxrowmarks;
2436 
2437  /* ... and mark the EPQ state inactive */
2438  epqstate->origslot = NULL;
2439  epqstate->recheckestate = NULL;
2440  epqstate->recheckplanstate = NULL;
2441  epqstate->relsubs_rowmark = NULL;
2442  epqstate->relsubs_done = NULL;
2443 }
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1108
#define NIL
Definition: pg_list.h:65
EState * parentestate
Definition: execnodes.h:1099
EState * recheckestate
Definition: execnodes.h:1129
List * arowMarks
Definition: execnodes.h:1116
List * tuple_table
Definition: execnodes.h:1107
bool * relsubs_done
Definition: execnodes.h:1142
TupleTableSlot * origslot
Definition: execnodes.h:1124
Plan * plan
Definition: execnodes.h:1115
void * palloc0(Size size)
Definition: mcxt.c:1093
unsigned int Index
Definition: c.h:549
Index es_range_table_size
Definition: execnodes.h:559
int epqParam
Definition: execnodes.h:1100
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1136
PlanState * recheckplanstate
Definition: execnodes.h:1144

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 2606 of file execMain.c.

References EState::es_query_cxt, ExecProcNode(), MemoryContextSwitchTo(), EPQState::recheckestate, and EPQState::recheckplanstate.

Referenced by EvalPlanQual(), and ExecLockRows().

2607 {
2608  MemoryContext oldcontext;
2609  TupleTableSlot *slot;
2610 
2611  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2612  slot = ExecProcNode(epqstate->recheckplanstate);
2613  MemoryContextSwitchTo(oldcontext);
2614 
2615  return slot;
2616 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:598
EState * recheckestate
Definition: execnodes.h:1129
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:252
PlanState * recheckplanstate
Definition: execnodes.h:1144

◆ EvalPlanQualSetPlan()

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

Definition at line 2452 of file execMain.c.

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

Referenced by ExecGetJunkAttribute(), and ExecInitModifyTable().

2453 {
2454  /* If we have a live EPQ query, shut it down */
2455  EvalPlanQualEnd(epqstate);
2456  /* And set/change the plan pointer */
2457  epqstate->plan = subplan;
2458  /* The rowmarks depend on the plan, too */
2459  epqstate->arowMarks = auxrowmarks;
2460 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2834
List * arowMarks
Definition: execnodes.h:1116
Plan * plan
Definition: execnodes.h:1115

◆ EvalPlanQualSlot()

TupleTableSlot* EvalPlanQualSlot ( EPQState epqstate,
Relation  relation,
Index  rti 
)

Definition at line 2469 of file execMain.c.

References Assert, EState::es_query_cxt, MemoryContextSwitchTo(), EPQState::parentestate, EPQState::relsubs_slot, table_slot_create(), and EPQState::tuple_table.

Referenced by EvalPlanQual(), ExecDelete(), ExecGetJunkAttribute(), ExecLockRows(), and ExecUpdate().

2471 {
2472  TupleTableSlot **slot;
2473 
2474  Assert(relation);
2475  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2476  slot = &epqstate->relsubs_slot[rti - 1];
2477 
2478  if (*slot == NULL)
2479  {
2480  MemoryContext oldcontext;
2481 
2482  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2483  *slot = table_slot_create(relation, &epqstate->tuple_table);
2484  MemoryContextSwitchTo(oldcontext);
2485  }
2486 
2487  return *slot;
2488 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1108
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
EState * parentestate
Definition: execnodes.h:1099
MemoryContext es_query_cxt
Definition: execnodes.h:598
List * tuple_table
Definition: execnodes.h:1107
#define Assert(condition)
Definition: c.h:804

◆ EvalPlanQualStart()

static void EvalPlanQualStart ( EPQState epqstate,
Plan planTree 
)
static

Definition at line 2683 of file execMain.c.

References EPQState::arowMarks, Assert, CreateExecutorState(), EState::es_crosscheck_snapshot, EState::es_direction, EState::es_epq_active, EState::es_instrument, EState::es_junkFilter, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_plannedstmt, EState::es_query_cxt, EState::es_queryEnv, EState::es_range_table, EState::es_range_table_size, EState::es_relations, EState::es_result_relations, EState::es_rowmarks, EState::es_snapshot, EState::es_subplanstates, EState::es_top_eflags, ExecInitNode(), ExecSetParamPlanMulti(), Plan::extParam, ForwardScanDirection, GetPerTupleExprContext, i, ParamExecData::isnull, lappend(), lfirst, list_length(), MemoryContextSwitchTo(), NIL, palloc0(), PlannedStmt::paramExecTypes, EPQState::parentestate, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_done, EPQState::relsubs_rowmark, ExecAuxRowMark::rowmark, ExecRowMark::rti, ExprEvalStep::subplan, PlannedStmt::subplans, and ParamExecData::value.

Referenced by EvalPlanQualBegin().

2684 {
2685  EState *parentestate = epqstate->parentestate;
2686  Index rtsize = parentestate->es_range_table_size;
2687  EState *rcestate;
2688  MemoryContext oldcontext;
2689  ListCell *l;
2690 
2691  epqstate->recheckestate = rcestate = CreateExecutorState();
2692 
2693  oldcontext = MemoryContextSwitchTo(rcestate->es_query_cxt);
2694 
2695  /* signal that this is an EState for executing EPQ */
2696  rcestate->es_epq_active = epqstate;
2697 
2698  /*
2699  * Child EPQ EStates share the parent's copy of unchanging state such as
2700  * the snapshot, rangetable, and external Param info. They need their own
2701  * copies of local state, including a tuple table, es_param_exec_vals,
2702  * result-rel info, etc.
2703  */
2704  rcestate->es_direction = ForwardScanDirection;
2705  rcestate->es_snapshot = parentestate->es_snapshot;
2706  rcestate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
2707  rcestate->es_range_table = parentestate->es_range_table;
2708  rcestate->es_range_table_size = parentestate->es_range_table_size;
2709  rcestate->es_relations = parentestate->es_relations;
2710  rcestate->es_queryEnv = parentestate->es_queryEnv;
2711  rcestate->es_rowmarks = parentestate->es_rowmarks;
2712  rcestate->es_plannedstmt = parentestate->es_plannedstmt;
2713  rcestate->es_junkFilter = parentestate->es_junkFilter;
2714  rcestate->es_output_cid = parentestate->es_output_cid;
2715 
2716  /*
2717  * ResultRelInfos needed by subplans are initialized from scratch when the
2718  * subplans themselves are initialized.
2719  */
2720  rcestate->es_result_relations = NULL;
2721  /* es_trig_target_relations must NOT be copied */
2722  rcestate->es_top_eflags = parentestate->es_top_eflags;
2723  rcestate->es_instrument = parentestate->es_instrument;
2724  /* es_auxmodifytables must NOT be copied */
2725 
2726  /*
2727  * The external param list is simply shared from parent. The internal
2728  * param workspace has to be local state, but we copy the initial values
2729  * from the parent, so as to have access to any param values that were
2730  * already set from other parts of the parent's plan tree.
2731  */
2732  rcestate->es_param_list_info = parentestate->es_param_list_info;
2733  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2734  {
2735  int i;
2736 
2737  /*
2738  * Force evaluation of any InitPlan outputs that could be needed by
2739  * the subplan. (With more complexity, maybe we could postpone this
2740  * till the subplan actually demands them, but it doesn't seem worth
2741  * the trouble; this is a corner case already, since usually the
2742  * InitPlans would have been evaluated before reaching EvalPlanQual.)
2743  *
2744  * This will not touch output params of InitPlans that occur somewhere
2745  * within the subplan tree, only those that are attached to the
2746  * ModifyTable node or above it and are referenced within the subplan.
2747  * That's OK though, because the planner would only attach such
2748  * InitPlans to a lower-level SubqueryScan node, and EPQ execution
2749  * will not descend into a SubqueryScan.
2750  *
2751  * The EState's per-output-tuple econtext is sufficiently short-lived
2752  * for this, since it should get reset before there is any chance of
2753  * doing EvalPlanQual again.
2754  */
2755  ExecSetParamPlanMulti(planTree->extParam,
2756  GetPerTupleExprContext(parentestate));
2757 
2758  /* now make the internal param workspace ... */
2759  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2760  rcestate->es_param_exec_vals = (ParamExecData *)
2761  palloc0(i * sizeof(ParamExecData));
2762  /* ... and copy down all values, whether really needed or not */
2763  while (--i >= 0)
2764  {
2765  /* copy value if any, but not execPlan link */
2766  rcestate->es_param_exec_vals[i].value =
2767  parentestate->es_param_exec_vals[i].value;
2768  rcestate->es_param_exec_vals[i].isnull =
2769  parentestate->es_param_exec_vals[i].isnull;
2770  }
2771  }
2772 
2773  /*
2774  * Initialize private state information for each SubPlan. We must do this
2775  * before running ExecInitNode on the main query tree, since
2776  * ExecInitSubPlan expects to be able to find these entries. Some of the
2777  * SubPlans might not be used in the part of the plan tree we intend to
2778  * run, but since it's not easy to tell which, we just initialize them
2779  * all.
2780  */
2781  Assert(rcestate->es_subplanstates == NIL);
2782  foreach(l, parentestate->es_plannedstmt->subplans)
2783  {
2784  Plan *subplan = (Plan *) lfirst(l);
2785  PlanState *subplanstate;
2786 
2787  subplanstate = ExecInitNode(subplan, rcestate, 0);
2788  rcestate->es_subplanstates = lappend(rcestate->es_subplanstates,
2789  subplanstate);
2790  }
2791 
2792  /*
2793  * Build an RTI indexed array of rowmarks, so that
2794  * EvalPlanQualFetchRowMark() can efficiently access the to be fetched
2795  * rowmark.
2796  */
2797  epqstate->relsubs_rowmark = (ExecAuxRowMark **)
2798  palloc0(rtsize * sizeof(ExecAuxRowMark *));
2799  foreach(l, epqstate->arowMarks)
2800  {
2801  ExecAuxRowMark *earm = (ExecAuxRowMark *) lfirst(l);
2802 
2803  epqstate->relsubs_rowmark[earm->rowmark->rti - 1] = earm;
2804  }
2805 
2806  /*
2807  * Initialize per-relation EPQ tuple states to not-fetched.
2808  */
2809  epqstate->relsubs_done = (bool *)
2810  palloc0(rtsize * sizeof(bool));
2811 
2812  /*
2813  * Initialize the private state information for all the nodes in the part
2814  * of the plan tree we need to run. This opens files, allocates storage
2815  * and leaves us ready to start processing tuples.
2816  */
2817  epqstate->recheckplanstate = ExecInitNode(planTree, rcestate, 0);
2818 
2819  MemoryContextSwitchTo(oldcontext);
2820 }
List * paramExecTypes
Definition: plannodes.h:84
#define NIL
Definition: pg_list.h:65
JunkFilter * es_junkFilter
Definition: execnodes.h:567
void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext)
Definition: nodeSubplan.c:1253
CommandId es_output_cid
Definition: execnodes.h:570
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlannedStmt * es_plannedstmt
Definition: execnodes.h:564
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:557
Snapshot es_snapshot
Definition: execnodes.h:556
List * es_range_table
Definition: execnodes.h:558
EState * parentestate
Definition: execnodes.h:1099
ScanDirection es_direction
Definition: execnodes.h:555
struct EPQState * es_epq_active
Definition: execnodes.h:627
ExecRowMark * rowmark
Definition: execnodes.h:694
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:562
#define GetPerTupleExprContext(estate)
Definition: executor.h:532
ParamExecData * es_param_exec_vals
Definition: execnodes.h:593
MemoryContext es_query_cxt
Definition: execnodes.h:598
EState * recheckestate
Definition: execnodes.h:1129
bool isnull
Definition: params.h:150
List * arowMarks
Definition: execnodes.h:1116
Index rti
Definition: execnodes.h:672
bool * relsubs_done
Definition: execnodes.h:1142
int es_instrument
Definition: execnodes.h:605
ResultRelInfo ** es_result_relations
Definition: execnodes.h:573
EState * CreateExecutorState(void)
Definition: execUtils.c:90
List * lappend(List *list, void *datum)
Definition: list.c:336
QueryEnvironment * es_queryEnv
Definition: execnodes.h:595
void * palloc0(Size size)
Definition: mcxt.c:1093
unsigned int Index
Definition: c.h:549
List * subplans
Definition: plannodes.h:73
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Relation * es_relations
Definition: execnodes.h:560
static int list_length(const List *l)
Definition: pg_list.h:149
Bitmapset * extParam
Definition: plannodes.h:159
Index es_range_table_size
Definition: execnodes.h:559
List * es_subplanstates
Definition: execnodes.h:610
int es_top_eflags
Definition: execnodes.h:604
int i
Datum value
Definition: params.h:149
ParamListInfo es_param_list_info
Definition: execnodes.h:592
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:141
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1136
PlanState * recheckplanstate
Definition: execnodes.h:1144

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2289 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 ExecGetJunkAttribute(), ExecInitLockRows(), and ExecInitModifyTable().

2290 {
2291  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2292  char resname[32];
2293 
2294  aerm->rowmark = erm;
2295 
2296  /* Look up the resjunk columns associated with this rowmark */
2297  if (erm->markType != ROW_MARK_COPY)
2298  {
2299  /* need ctid for all methods other than COPY */
2300  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2301  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2302  resname);
2303  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2304  elog(ERROR, "could not find junk %s column", resname);
2305  }
2306  else
2307  {
2308  /* need wholerow if COPY */
2309  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2310  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2311  resname);
2312  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2313  elog(ERROR, "could not find junk %s column", resname);
2314  }
2315 
2316  /* if child rel, need tableoid */
2317  if (erm->rti != erm->prti)
2318  {
2319  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2320  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2321  resname);
2322  if (!AttributeNumberIsValid(aerm->toidAttNo))
2323  elog(ERROR, "could not find junk %s column", resname);
2324  }
2325 
2326  return aerm;
2327 }
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:222
ExecRowMark * rowmark
Definition: execnodes.h:694
#define ERROR
Definition: elog.h:46
Index rti
Definition: execnodes.h:672
AttrNumber wholeAttNo
Definition: execnodes.h:697
Index prti
Definition: execnodes.h:673
Index rowmarkId
Definition: execnodes.h:674
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void * palloc0(Size size)
Definition: mcxt.c:1093
RowMarkType markType
Definition: execnodes.h:675
AttrNumber toidAttNo
Definition: execnodes.h:696
#define elog(elevel,...)
Definition: elog.h:232
#define snprintf
Definition: port.h:216
AttrNumber ctidAttNo
Definition: execnodes.h:695

◆ ExecBuildSlotValueDescription()

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

Definition at line 2103 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, StringInfoData::len, NameStr, TupleDescData::natts, OidOutputFunctionCall(), pg_attribute_aclcheck(), pg_class_aclcheck(), pg_mbcliplen(), RLS_ENABLED, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TupleDescAttr, and val.

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

2108 {
2110  StringInfoData collist;
2111  bool write_comma = false;
2112  bool write_comma_collist = false;
2113  int i;
2114  AclResult aclresult;
2115  bool table_perm = false;
2116  bool any_perm = false;
2117 
2118  /*
2119  * Check if RLS is enabled and should be active for the relation; if so,
2120  * then don't return anything. Otherwise, go through normal permission
2121  * checks.
2122  */
2123  if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2124  return NULL;
2125 
2126  initStringInfo(&buf);
2127 
2128  appendStringInfoChar(&buf, '(');
2129 
2130  /*
2131  * Check if the user has permissions to see the row. Table-level SELECT
2132  * allows access to all columns. If the user does not have table-level
2133  * SELECT then we check each column and include those the user has SELECT
2134  * rights on. Additionally, we always include columns the user provided
2135  * data for.
2136  */
2137  aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2138  if (aclresult != ACLCHECK_OK)
2139  {
2140  /* Set up the buffer for the column list */
2141  initStringInfo(&collist);
2142  appendStringInfoChar(&collist, '(');
2143  }
2144  else
2145  table_perm = any_perm = true;
2146 
2147  /* Make sure the tuple is fully deconstructed */
2148  slot_getallattrs(slot);
2149 
2150  for (i = 0; i < tupdesc->natts; i++)
2151  {
2152  bool column_perm = false;
2153  char *val;
2154  int vallen;
2155  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2156 
2157  /* ignore dropped columns */
2158  if (att->attisdropped)
2159  continue;
2160 
2161  if (!table_perm)
2162  {
2163  /*
2164  * No table-level SELECT, so need to make sure they either have
2165  * SELECT rights on the column or that they have provided the data
2166  * for the column. If not, omit this column from the error
2167  * message.
2168  */
2169  aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2170  GetUserId(), ACL_SELECT);
2172  modifiedCols) || aclresult == ACLCHECK_OK)
2173  {
2174  column_perm = any_perm = true;
2175 
2176  if (write_comma_collist)
2177  appendStringInfoString(&collist, ", ");
2178  else
2179  write_comma_collist = true;
2180 
2181  appendStringInfoString(&collist, NameStr(att->attname));
2182  }
2183  }
2184 
2185  if (table_perm || column_perm)
2186  {
2187  if (slot->tts_isnull[i])
2188  val = "null";
2189  else
2190  {
2191  Oid foutoid;
2192  bool typisvarlena;
2193 
2194  getTypeOutputInfo(att->atttypid,
2195  &foutoid, &typisvarlena);
2196  val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2197  }
2198 
2199  if (write_comma)
2200  appendStringInfoString(&buf, ", ");
2201  else
2202  write_comma = true;
2203 
2204  /* truncate if needed */
2205  vallen = strlen(val);
2206  if (vallen <= maxfieldlen)
2207  appendBinaryStringInfo(&buf, val, vallen);
2208  else
2209  {
2210  vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2211  appendBinaryStringInfo(&buf, val, vallen);
2212  appendStringInfoString(&buf, "...");
2213  }
2214  }
2215  }
2216 
2217  /* If we end up with zero columns being returned, then return NULL. */
2218  if (!any_perm)
2219  return NULL;
2220 
2221  appendStringInfoChar(&buf, ')');
2222 
2223  if (!table_perm)
2224  {
2225  appendStringInfoString(&collist, ") = ");
2226  appendBinaryStringInfo(&collist, buf.data, buf.len);
2227 
2228  return collist.data;
2229  }
2230 
2231  return buf.data;
2232 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2854
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4556
Oid GetUserId(void)
Definition: miscinit.c:478
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Datum * tts_values
Definition: tuptable.h:126
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
unsigned int Oid
Definition: postgres_ext.h:31
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1026
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:354
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
bool * tts_isnull
Definition: tuptable.h:128
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
AclResult
Definition: acl.h:177
#define ACL_SELECT
Definition: parsenodes.h:83
#define InvalidOid
Definition: postgres_ext.h:36
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4685
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1653
int i
#define NameStr(name)
Definition: c.h:681
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
long val
Definition: informix.c:664

◆ 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:4556
Oid GetUserId(void)
Definition: miscinit.c:478
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
AclMode requiredPerms
Definition: parsenodes.h:1145
unsigned int Oid
Definition: postgres_ext.h:31
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3825
uint32 AclMode
Definition: parsenodes.h:80
Bitmapset * selectedCols
Definition: parsenodes.h:1147
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:701
#define ACL_UPDATE
Definition: parsenodes.h:84
#define ACL_SELECT
Definition: parsenodes.h:83
Bitmapset * updatedCols
Definition: parsenodes.h:1149
#define ACL_INSERT
Definition: parsenodes.h:82
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4600
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:995
Bitmapset * insertedCols
Definition: parsenodes.h:1148
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:4556
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define ERROR
Definition: elog.h:46
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4600
#define InvalidAttrNumber
Definition: attnum.h:23
#define elog(elevel,...)
Definition: elog.h:232
int16 AttrNumber
Definition: attnum.h:21

◆ ExecCheckRTPerms()

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

Definition at line 568 of file execMain.c.

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

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

569 {
570  ListCell *l;
571  bool result = true;
572 
573  foreach(l, rangeTable)
574  {
575  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
576 
577  result = ExecCheckRTEPerms(rte);
578  if (!result)
579  {
580  Assert(rte->rtekind == RTE_RELATION);
581  if (ereport_on_violation)
583  get_rel_name(rte->relid));
584  return false;
585  }
586  }
587 
589  result = (*ExecutorCheckPerms_hook) (rangeTable,
590  ereport_on_violation);
591  return result;
592 }
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1974
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
static bool ExecCheckRTEPerms(RangeTblEntry *rte)
Definition: execMain.c:599
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:77
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
RTEKind rtekind
Definition: parsenodes.h:995
ObjectType get_relkind_objtype(char relkind)
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1899

◆ ExecCheckXactReadOnly()

static void ExecCheckXactReadOnly ( PlannedStmt plannedstmt)
static

Definition at line 766 of file execMain.c.

References ACL_SELECT, CMD_SELECT, PlannedStmt::commandType, CreateCommandName(), 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:426
static const char * CreateCommandName(Node *parsetree)
Definition: utility.h:99
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1923
Definition: nodes.h:539
AclMode requiredPerms
Definition: parsenodes.h:1145
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3156
CmdType commandType
Definition: plannodes.h:46
#define ACL_SELECT
Definition: parsenodes.h:83
#define lfirst(lc)
Definition: pg_list.h:169
bool hasModifyingCTE
Definition: plannodes.h:52
List * rtable
Definition: plannodes.h:66
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:408
RTEKind rtekind
Definition: parsenodes.h:995

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1482 of file execMain.c.

References EState::es_range_table_size, EState::es_relations, i, NoLock, and table_close().

Referenced by CopyFrom(), and ExecEndPlan().

1483 {
1484  int i;
1485 
1486  for (i = 0; i < estate->es_range_table_size; i++)
1487  {
1488  if (estate->es_relations[i])
1489  table_close(estate->es_relations[i], NoLock);
1490  }
1491 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define NoLock
Definition: lockdefs.h:34
Relation * es_relations
Definition: execnodes.h:560
Index es_range_table_size
Definition: execnodes.h:559
int i

◆ ExecCloseResultRelations()

void ExecCloseResultRelations ( EState estate)

Definition at line 1439 of file execMain.c.

References Assert, EState::es_opened_result_relations, EState::es_trig_target_relations, ExecCloseIndices(), lfirst, NoLock, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RangeTableIndex, ResultRelInfo::ri_RelationDesc, and table_close().

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

1440 {
1441  ListCell *l;
1442 
1443  /*
1444  * close indexes of result relation(s) if any. (Rels themselves are
1445  * closed in ExecCloseRangeTableRelations())
1446  */
1447  foreach(l, estate->es_opened_result_relations)
1448  {
1449  ResultRelInfo *resultRelInfo = lfirst(l);
1450 
1451  ExecCloseIndices(resultRelInfo);
1452  }
1453 
1454  /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
1455  foreach(l, estate->es_trig_target_relations)
1456  {
1457  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1458 
1459  /*
1460  * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
1461  * might be issuing a duplicate close against a Relation opened by
1462  * ExecGetRangeTableRelation.
1463  */
1464  Assert(resultRelInfo->ri_RangeTableIndex == 0);
1465 
1466  /*
1467  * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
1468  * these rels, we needn't call ExecCloseIndices either.
1469  */
1470  Assert(resultRelInfo->ri_NumIndices == 0);
1471 
1472  table_close(resultRelInfo->ri_RelationDesc, NoLock);
1473  }
1474 }
int ri_NumIndices
Definition: execnodes.h:414
Relation ri_RelationDesc
Definition: execnodes.h:411
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Index ri_RangeTableIndex
Definition: execnodes.h:408
#define NoLock
Definition: lockdefs.h:34
List * es_opened_result_relations
Definition: execnodes.h:576
List * es_trig_target_relations
Definition: execnodes.h:589
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:231

◆ ExecConstraints()

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

Definition at line 1821 of file execMain.c.

References Assert, bms_union(), build_attrmap_by_name_if_req(), TupleDescData::constr, ereport, errcode(), errdetail(), errmsg(), ERROR, errtablecol(), errtableconstraint(), ExecBuildSlotValueDescription(), ExecGetInsertedCols(), ExecGetUpdatedCols(), ExecRelCheck(), execute_attr_map_slot(), TupleConstr::has_not_null, MakeTupleTableSlot(), ExprEvalStep::map, NameStr, TupleDescData::natts, RelationData::rd_rel, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, slot_attisnull(), TTSOpsVirtual, ExprEvalStep::tupdesc, and TupleDescAttr.

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

1823 {
1824  Relation rel = resultRelInfo->ri_RelationDesc;
1825  TupleDesc tupdesc = RelationGetDescr(rel);
1826  TupleConstr *constr = tupdesc->constr;
1827  Bitmapset *modifiedCols;
1828 
1829  Assert(constr); /* we should not be called otherwise */
1830 
1831  if (constr->has_not_null)
1832  {
1833  int natts = tupdesc->natts;
1834  int attrChk;
1835 
1836  for (attrChk = 1; attrChk <= natts; attrChk++)
1837  {
1838  Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
1839 
1840  if (att->attnotnull && slot_attisnull(slot, attrChk))
1841  {
1842  char *val_desc;
1843  Relation orig_rel = rel;
1844  TupleDesc orig_tupdesc = RelationGetDescr(rel);
1845 
1846  /*
1847  * If the tuple has been routed, it's been converted to the
1848  * partition's rowtype, which might differ from the root
1849  * table's. We must convert it back to the root table's
1850  * rowtype so that val_desc shown error message matches the
1851  * input tuple.
1852  */
1853  if (resultRelInfo->ri_RootResultRelInfo)
1854  {
1855  ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1856  AttrMap *map;
1857 
1858  tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1859  /* a reverse map */
1860  map = build_attrmap_by_name_if_req(orig_tupdesc,
1861  tupdesc);
1862 
1863  /*
1864  * Partition-specific slot's tupdesc can't be changed, so
1865  * allocate a new one.
1866  */
1867  if (map != NULL)
1868  slot = execute_attr_map_slot(map, slot,
1869  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
1870  modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
1871  ExecGetUpdatedCols(rootrel, estate));
1872  rel = rootrel->ri_RelationDesc;
1873  }
1874  else
1875  modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1876  ExecGetUpdatedCols(resultRelInfo, estate));
1878  slot,
1879  tupdesc,
1880  modifiedCols,
1881  64);
1882 
1883  ereport(ERROR,
1884  (errcode(ERRCODE_NOT_NULL_VIOLATION),
1885  errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
1886  NameStr(att->attname),
1887  RelationGetRelationName(orig_rel)),
1888  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1889  errtablecol(orig_rel, attrChk)));
1890  }
1891  }
1892  }
1893 
1894  if (rel->rd_rel->relchecks > 0)
1895  {
1896  const char *failed;
1897 
1898  if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
1899  {
1900  char *val_desc;
1901  Relation orig_rel = rel;
1902 
1903  /* See the comment above. */
1904  if (resultRelInfo->ri_RootResultRelInfo)
1905  {
1906  ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1907  TupleDesc old_tupdesc = RelationGetDescr(rel);
1908  AttrMap *map;
1909 
1910  tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1911  /* a reverse map */
1912  map = build_attrmap_by_name_if_req(old_tupdesc,
1913  tupdesc);
1914 
1915  /*
1916  * Partition-specific slot's tupdesc can't be changed, so
1917  * allocate a new one.
1918  */
1919  if (map != NULL)
1920  slot = execute_attr_map_slot(map, slot,
1921  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
1922  modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
1923  ExecGetUpdatedCols(rootrel, estate));
1924  rel = rootrel->ri_RelationDesc;
1925  }
1926  else
1927  modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1928  ExecGetUpdatedCols(resultRelInfo, estate));
1930  slot,
1931  tupdesc,
1932  modifiedCols,
1933  64);
1934  ereport(ERROR,
1935  (errcode(ERRCODE_CHECK_VIOLATION),
1936  errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
1937  RelationGetRelationName(orig_rel), failed),
1938  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1939  errtableconstraint(orig_rel, failed)));
1940  }
1941  }
1942 }
Relation ri_RelationDesc
Definition: execnodes.h:411
#define RelationGetDescr(relation)
Definition: rel.h:495
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1295
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
int errcode(int sqlerrcode)
Definition: elog.c:698
Form_pg_class rd_rel
Definition: rel.h:109
Definition: attmap.h:34
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5682
AttrMap * build_attrmap_by_name_if_req(TupleDesc indesc, TupleDesc outdesc)
Definition: attmap.c:259
#define ERROR
Definition: elog.h:46
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2103
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:511
TupleConstr * constr
Definition: tupdesc.h:85
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define RelationGetRelationName(relation)
Definition: rel.h:503
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1112
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1622
#define ereport(elevel,...)
Definition: elog.h:157
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
#define Assert(condition)
Definition: c.h:804
int errtablecol(Relation rel, int attnum)
Definition: relcache.c:5645
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:225
Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1256
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NameStr(name)
Definition: c.h:681
bool has_not_null
Definition: tupdesc.h:44
static bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: tuptable.h:367
#define RelationGetRelid(relation)
Definition: rel.h:469

◆ ExecEndPlan()

static void ExecEndPlan ( PlanState planstate,
EState estate 
)
static

Definition at line 1400 of file execMain.c.

References EState::es_subplanstates, EState::es_tupleTable, ExecCloseRangeTableRelations(), ExecCloseResultRelations(), ExecEndNode(), ExecResetTupleTable(), and lfirst.

Referenced by standard_ExecutorEnd().

1401 {
1402  ListCell *l;
1403 
1404  /*
1405  * shut down the node-type-specific query processing
1406  */
1407  ExecEndNode(planstate);
1408 
1409  /*
1410  * for subplans too
1411  */
1412  foreach(l, estate->es_subplanstates)
1413  {
1414  PlanState *subplanstate = (PlanState *) lfirst(l);
1415 
1416  ExecEndNode(subplanstate);
1417  }
1418 
1419  /*
1420  * destroy the executor's tuple table. Actually we only care about
1421  * releasing buffer pins and tupdesc refcounts; there's no need to pfree
1422  * the TupleTableSlots, since the containing memory context is about to go
1423  * away anyway.
1424  */
1425  ExecResetTupleTable(estate->es_tupleTable, false);
1426 
1427  /*
1428  * Close any Relations that have been opened for range table entries or
1429  * result relations.
1430  */
1431  ExecCloseResultRelations(estate);
1433 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:555
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1439
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1482
List * es_tupleTable
Definition: execnodes.h:600
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1191
#define lfirst(lc)
Definition: pg_list.h:169
List * es_subplanstates
Definition: execnodes.h:610

◆ ExecFindRowMark()

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

Definition at line 2266 of file execMain.c.

References elog, ERROR, and EState::es_rowmarks.

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

2267 {
2268  if (rti > 0 && rti <= estate->es_range_table_size &&
2269  estate->es_rowmarks != NULL)
2270  {
2271  ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2272 
2273  if (erm)
2274  return erm;
2275  }
2276  if (!missing_ok)
2277  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2278  return NULL;
2279 }
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:562
#define ERROR
Definition: elog.h:46
#define elog(elevel,...)
Definition: elog.h:232

◆ ExecGetTriggerResultRel()

ResultRelInfo* ExecGetTriggerResultRel ( EState estate,
Oid  relid 
)

Definition at line 1282 of file execMain.c.

References EState::es_instrument, EState::es_opened_result_relations, EState::es_query_cxt, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, InitResultRelInfo(), lappend(), lfirst, makeNode, MemoryContextSwitchTo(), NoLock, RelationGetRelid, ResultRelInfo::ri_RelationDesc, and table_open().

Referenced by afterTriggerInvokeEvents(), and ExecGetJunkAttribute().

1283 {
1284  ResultRelInfo *rInfo;
1285  ListCell *l;
1286  Relation rel;
1287  MemoryContext oldcontext;
1288 
1289  /* Search through the query result relations */
1290  foreach(l, estate->es_opened_result_relations)
1291  {
1292  rInfo = lfirst(l);
1293  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1294  return rInfo;
1295  }
1296 
1297  /*
1298  * Search through the result relations that were created during tuple
1299  * routing, if any.
1300  */
1301  foreach(l, estate->es_tuple_routing_result_relations)
1302  {
1303  rInfo = (ResultRelInfo *) lfirst(l);
1304  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1305  return rInfo;
1306  }
1307 
1308  /* Nope, but maybe we already made an extra ResultRelInfo for it */
1309  foreach(l, estate->es_trig_target_relations)
1310  {
1311  rInfo = (ResultRelInfo *) lfirst(l);
1312  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1313  return rInfo;
1314  }
1315  /* Nope, so we need a new one */
1316 
1317  /*
1318  * Open the target relation's relcache entry. We assume that an
1319  * appropriate lock is still held by the backend from whenever the trigger
1320  * event got queued, so we need take no new lock here. Also, we need not
1321  * recheck the relkind, so no need for CheckValidResultRel.
1322  */
1323  rel = table_open(relid, NoLock);
1324 
1325  /*
1326  * Make the new entry in the right context.
1327  */
1328  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1329  rInfo = makeNode(ResultRelInfo);
1330  InitResultRelInfo(rInfo,
1331  rel,
1332  0, /* dummy rangetable index */
1333  NULL,
1334  estate->es_instrument);
1335  estate->es_trig_target_relations =
1336  lappend(estate->es_trig_target_relations, rInfo);
1337  MemoryContextSwitchTo(oldcontext);
1338 
1339  /*
1340  * Currently, we don't need any index information in ResultRelInfos used
1341  * only for triggers, so no need to call ExecOpenIndices.
1342  */
1343 
1344  return rInfo;
1345 }
Relation ri_RelationDesc
Definition: execnodes.h:411
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:598
#define NoLock
Definition: lockdefs.h:34
List * es_opened_result_relations
Definition: execnodes.h:576
int es_instrument
Definition: execnodes.h:605
List * lappend(List *list, void *datum)
Definition: list.c:336
List * es_trig_target_relations
Definition: execnodes.h:589
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
Definition: execMain.c:1193
List * es_tuple_routing_result_relations
Definition: execnodes.h:586
#define makeNode(_type_)
Definition: nodes.h:587
#define lfirst(lc)
Definition: pg_list.h:169
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:469

◆ ExecPartitionCheck()

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

Definition at line 1697 of file execMain.c.

References ExprContext::ecxt_scantuple, EState::es_query_cxt, ExecCheck(), ExecPartitionCheckEmitError(), ExecPrepareCheck(), GetPerTupleExprContext, MemoryContextSwitchTo(), RelationGetPartitionQual(), ResultRelInfo::ri_PartitionCheckExpr, ResultRelInfo::ri_RelationDesc, and success.

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

1699 {
1700  ExprContext *econtext;
1701  bool success;
1702 
1703  /*
1704  * If first time through, build expression state tree for the partition
1705  * check expression. (In the corner case where the partition check
1706  * expression is empty, ie there's a default partition and nothing else,
1707  * we'll be fooled into executing this code each time through. But it's
1708  * pretty darn cheap in that case, so we don't worry about it.)
1709  */
1710  if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1711  {
1712  /*
1713  * Ensure that the qual tree and prepared expression are in the
1714  * query-lifespan context.
1715  */
1717  List *qual = RelationGetPartitionQual(resultRelInfo->ri_RelationDesc);
1718 
1719  resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1720  MemoryContextSwitchTo(oldcxt);
1721  }
1722 
1723  /*
1724  * We will use the EState's per-tuple context for evaluating constraint
1725  * expressions (creating it if it's not already there).
1726  */
1727  econtext = GetPerTupleExprContext(estate);
1728 
1729  /* Arrange for econtext's scan tuple to be the tuple under test */
1730  econtext->ecxt_scantuple = slot;
1731 
1732  /*
1733  * As in case of the catalogued constraints, we treat a NULL result as
1734  * success here, not a failure.
1735  */
1736  success = ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
1737 
1738  /* if asked to emit error, don't actually return on failure */
1739  if (!success && emitError)
1740  ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
1741 
1742  return success;
1743 }
Relation ri_RelationDesc
Definition: execnodes.h:411
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:743
ExprState * ri_PartitionCheckExpr
Definition: execnodes.h:497
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define GetPerTupleExprContext(estate)
Definition: executor.h:532
MemoryContext es_query_cxt
Definition: execnodes.h:598
void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1750
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
List * RelationGetPartitionQual(Relation rel)
Definition: partcache.c:276
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:799
static bool success
Definition: initdb.c:165
Definition: pg_list.h:50

◆ ExecPartitionCheckEmitError()

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

Definition at line 1750 of file execMain.c.

References bms_union(), build_attrmap_by_name_if_req(), ereport, errcode(), errdetail(), errmsg(), ERROR, errtable(), ExecBuildSlotValueDescription(), ExecGetInsertedCols(), ExecGetUpdatedCols(), execute_attr_map_slot(), MakeTupleTableSlot(), ExprEvalStep::map, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, TTSOpsVirtual, and ExprEvalStep::tupdesc.

Referenced by ExecCrossPartitionUpdate(), ExecGetJunkAttribute(), and ExecPartitionCheck().

1753 {
1754  Oid root_relid;
1755  TupleDesc tupdesc;
1756  char *val_desc;
1757  Bitmapset *modifiedCols;
1758 
1759  /*
1760  * If the tuple has been routed, it's been converted to the partition's
1761  * rowtype, which might differ from the root table's. We must convert it
1762  * back to the root table's rowtype so that val_desc in the error message
1763  * matches the input tuple.
1764  */
1765  if (resultRelInfo->ri_RootResultRelInfo)
1766  {
1767  ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1768  TupleDesc old_tupdesc;
1769  AttrMap *map;
1770 
1771  root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
1772  tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1773 
1774  old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1775  /* a reverse map */
1776  map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc);
1777 
1778  /*
1779  * Partition-specific slot's tupdesc can't be changed, so allocate a
1780  * new one.
1781  */
1782  if (map != NULL)
1783  slot = execute_attr_map_slot(map, slot,
1784  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
1785  modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
1786  ExecGetUpdatedCols(rootrel, estate));
1787  }
1788  else
1789  {
1790  root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1791  tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1792  modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1793  ExecGetUpdatedCols(resultRelInfo, estate));
1794  }
1795 
1796  val_desc = ExecBuildSlotValueDescription(root_relid,
1797  slot,
1798  tupdesc,
1799  modifiedCols,
1800  64);
1801  ereport(ERROR,
1802  (errcode(ERRCODE_CHECK_VIOLATION),
1803  errmsg("new row for relation \"%s\" violates partition constraint",
1804  RelationGetRelationName(resultRelInfo->ri_RelationDesc)),
1805  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1806  errtable(resultRelInfo->ri_RelationDesc)));
1807 }
Relation ri_RelationDesc
Definition: execnodes.h:411
#define RelationGetDescr(relation)
Definition: rel.h:495
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1295
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
Definition: attmap.h:34
AttrMap * build_attrmap_by_name_if_req(TupleDesc indesc, TupleDesc outdesc)
Definition: attmap.c:259
#define ERROR
Definition: elog.h:46
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2103
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:511
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define RelationGetRelationName(relation)
Definition: rel.h:503
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1112
#define ereport(elevel,...)
Definition: elog.h:157
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:225
Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1256
int errmsg(const char *fmt,...)
Definition: elog.c:909
int errtable(Relation rel)
Definition: relcache.c:5628
#define RelationGetRelid(relation)
Definition: rel.h:469

◆ ExecPostprocessPlan()

static void ExecPostprocessPlan ( EState estate)
static

Definition at line 1354 of file execMain.c.

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

Referenced by standard_ExecutorFinish().

1355 {
1356  ListCell *lc;
1357 
1358  /*
1359  * Make sure nodes run forward.
1360  */
1362 
1363  /*
1364  * Run any secondary ModifyTable nodes to completion, in case the main
1365  * query did not fetch all rows from them. (We do this to ensure that
1366  * such nodes have predictable results.)
1367  */
1368  foreach(lc, estate->es_auxmodifytables)
1369  {
1370  PlanState *ps = (PlanState *) lfirst(lc);
1371 
1372  for (;;)
1373  {
1374  TupleTableSlot *slot;
1375 
1376  /* Reset the per-output-tuple exprcontext each time */
1377  ResetPerTupleExprContext(estate);
1378 
1379  slot = ExecProcNode(ps);
1380 
1381  if (TupIsNull(slot))
1382  break;
1383  }
1384  }
1385 }
#define ResetPerTupleExprContext(estate)
Definition: executor.h:541
ScanDirection es_direction
Definition: execnodes.h:555
#define TupIsNull(slot)
Definition: tuptable.h:292
List * es_auxmodifytables
Definition: execnodes.h:612
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:252
#define lfirst(lc)
Definition: pg_list.h:169

◆ ExecRelCheck()

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

Definition at line 1622 of file execMain.c.

References ConstrCheck::ccname, TupleConstr::check, TupleDescData::constr, ExprContext::ecxt_scantuple, elog, ERROR, EState::es_query_cxt, ExecCheck(), ExecPrepareExpr(), GetPerTupleExprContext, i, MemoryContextSwitchTo(), TupleConstr::num_check, palloc(), RelationData::rd_att, RelationData::rd_rel, RelationGetRelationName, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_RelationDesc, and stringToNode().

Referenced by ExecConstraints().

1624 {
1625  Relation rel = resultRelInfo->ri_RelationDesc;
1626  int ncheck = rel->rd_att->constr->num_check;
1627  ConstrCheck *check = rel->rd_att->constr->check;
1628  ExprContext *econtext;
1629  MemoryContext oldContext;
1630  int i;
1631 
1632  /*
1633  * CheckConstraintFetch let this pass with only a warning, but now we
1634  * should fail rather than possibly failing to enforce an important
1635  * constraint.
1636  */
1637  if (ncheck != rel->rd_rel->relchecks)
1638  elog(ERROR, "%d pg_constraint record(s) missing for relation \"%s\"",
1639  rel->rd_rel->relchecks - ncheck, RelationGetRelationName(rel));
1640 
1641  /*
1642  * If first time through for this result relation, build expression
1643  * nodetrees for rel's constraint expressions. Keep them in the per-query
1644  * memory context so they'll survive throughout the query.
1645  */
1646  if (resultRelInfo->ri_ConstraintExprs == NULL)
1647  {
1648  oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
1649  resultRelInfo->ri_ConstraintExprs =
1650  (ExprState **) palloc(ncheck * sizeof(ExprState *));
1651  for (i = 0; i < ncheck; i++)
1652  {
1653  Expr *checkconstr;
1654 
1655  checkconstr = stringToNode(check[i].ccbin);
1656  resultRelInfo->ri_ConstraintExprs[i] =
1657  ExecPrepareExpr(checkconstr, estate);
1658  }
1659  MemoryContextSwitchTo(oldContext);
1660  }
1661 
1662  /*
1663  * We will use the EState's per-tuple context for evaluating constraint
1664  * expressions (creating it if it's not already there).
1665  */
1666  econtext = GetPerTupleExprContext(estate);
1667 
1668  /* Arrange for econtext's scan tuple to be the tuple under test */
1669  econtext->ecxt_scantuple = slot;
1670 
1671  /* And evaluate the constraints */
1672  for (i = 0; i < ncheck; i++)
1673  {
1674  ExprState *checkconstr = resultRelInfo->ri_ConstraintExprs[i];
1675 
1676  /*
1677  * NOTE: SQL specifies that a NULL result from a constraint expression
1678  * is not to be treated as a failure. Therefore, use ExecCheck not
1679  * ExecQual.
1680  */
1681  if (!ExecCheck(checkconstr, econtext))
1682  return check[i].ccname;
1683  }
1684 
1685  /* NULL result means no error */
1686  return NULL;
1687 }
Relation ri_RelationDesc
Definition: execnodes.h:411
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void * stringToNode(const char *str)
Definition: read.c:89
Form_pg_class rd_rel
Definition: rel.h:109
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:692
#define GetPerTupleExprContext(estate)
Definition: executor.h:532
MemoryContext es_query_cxt
Definition: execnodes.h:598
#define ERROR
Definition: elog.h:46
TupleConstr * constr
Definition: tupdesc.h:85
char * ccname
Definition: tupdesc.h:30
#define RelationGetRelationName(relation)
Definition: rel.h:503
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:476
TupleDesc rd_att
Definition: rel.h:110
uint16 num_check
Definition: tupdesc.h:43
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
int i
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:799
ConstrCheck * check
Definition: tupdesc.h:40

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2240 of file execMain.c.

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

Referenced by ExecBRUpdateTriggers(), ExecGetJunkAttribute(), and ExecOnConflictUpdate().

2241 {
2242  Bitmapset *keyCols;
2243  Bitmapset *updatedCols;
2244 
2245  /*
2246  * Compute lock mode to use. If columns that are part of the key have not
2247  * been modified, then we can use a weaker lock, allowing for better
2248  * concurrency.
2249  */
2250  updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2251  keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2253 
2254  if (bms_overlap(keyCols, updatedCols))
2255  return LockTupleExclusive;
2256 
2257  return LockTupleNoKeyExclusive;
2258 }
Relation ri_RelationDesc
Definition: execnodes.h:411
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1347
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:5000

◆ 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 1506 of file execMain.c.

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

Referenced by standard_ExecutorRun().

1515 {
1516  TupleTableSlot *slot;
1517  uint64 current_tuple_count;
1518 
1519  /*
1520  * initialize local variables
1521  */
1522  current_tuple_count = 0;
1523 
1524  /*
1525  * Set the direction.
1526  */
1527  estate->es_direction = direction;
1528 
1529  /*
1530  * If the plan might potentially be executed multiple times, we must force
1531  * it to run without parallelism, because we might exit early.
1532  */
1533  if (!execute_once)
1534  use_parallel_mode = false;
1535 
1536  estate->es_use_parallel_mode = use_parallel_mode;
1537  if (use_parallel_mode)
1539 
1540  /*
1541  * Loop until we've processed the proper number of tuples from the plan.
1542  */
1543  for (;;)
1544  {
1545  /* Reset the per-output-tuple exprcontext */
1546  ResetPerTupleExprContext(estate);
1547 
1548  /*
1549  * Execute the plan and obtain a tuple
1550  */
1551  slot = ExecProcNode(planstate);
1552 
1553  /*
1554  * if the tuple is null, then we assume there is nothing more to
1555  * process so we just end the loop...
1556  */
1557  if (TupIsNull(slot))
1558  break;
1559 
1560  /*
1561  * If we have a junk filter, then project a new tuple with the junk
1562  * removed.
1563  *
1564  * Store this new "clean" tuple in the junkfilter's resultSlot.
1565  * (Formerly, we stored it back over the "dirty" tuple, which is WRONG
1566  * because that tuple slot has the wrong descriptor.)
1567  */
1568  if (estate->es_junkFilter != NULL)
1569  slot = ExecFilterJunk(estate->es_junkFilter, slot);
1570 
1571  /*
1572  * If we are supposed to send the tuple somewhere, do so. (In
1573  * practice, this is probably always the case at this point.)
1574  */
1575  if (sendTuples)
1576  {
1577  /*
1578  * If we are not able to send the tuple, we assume the destination
1579  * has closed and no more tuples can be sent. If that's the case,
1580  * end the loop.
1581  */
1582  if (!dest->receiveSlot(slot, dest))
1583  break;
1584  }
1585 
1586  /*
1587  * Count tuples processed, if this is a SELECT. (For other operation
1588  * types, the ModifyTable plan node must count the appropriate
1589  * events.)
1590  */
1591  if (operation == CMD_SELECT)
1592  (estate->es_processed)++;
1593 
1594  /*
1595  * check our tuple count.. if we've processed the proper number then
1596  * quit, else loop again and process more tuples. Zero numberTuples
1597  * means no limit.
1598  */
1599  current_tuple_count++;
1600  if (numberTuples && numberTuples == current_tuple_count)
1601  break;
1602  }
1603 
1604  /*
1605  * If we know we won't need to back up, we can release resources at this
1606  * point.
1607  */
1608  if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))
1609  (void) ExecShutdownNode(planstate);
1610 
1611  if (use_parallel_mode)
1612  ExitParallelMode();
1613 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:119
JunkFilter * es_junkFilter
Definition: execnodes.h:567
#define ResetPerTupleExprContext(estate)
Definition: executor.h:541
bool ExecShutdownNode(PlanState *node)
Definition: execProcnode.c:771
ScanDirection es_direction
Definition: execnodes.h:555
bool es_use_parallel_mode
Definition: execnodes.h:629
void ExitParallelMode(void)
Definition: xact.c:992
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define TupIsNull(slot)
Definition: tuptable.h:292
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:247
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:252
uint64 es_processed
Definition: execnodes.h:602
void EnterParallelMode(void)
Definition: xact.c:979
int es_top_eflags
Definition: execnodes.h:604

◆ 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(), ExecGetJunkAttribute(), 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:74

◆ 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(), ExecGetJunkAttribute(), 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:73

◆ 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(), ExecGetJunkAttribute(), 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:78
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:598
PlanState * planstate
Definition: execdesc.h:49
CmdType operation
Definition: execdesc.h:36
#define Assert(condition)
Definition: c.h:804

◆ ExecutorRun()

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

Definition at line 298 of file execMain.c.

References ExecutorRun_hook, and standard_ExecutorRun().

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

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

◆ ExecutorStart()

void ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 130 of file execMain.c.

References ExecutorStart_hook, pgstat_report_query_id(), QueryDesc::plannedstmt, PlannedStmt::queryId, and standard_ExecutorStart().

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

131 {
132  /*
133  * In some cases (e.g. an EXECUTE statement) a query execution will skip
134  * parse analysis, which means that the query_id won't be reported. Note
135  * that it's harmless to report the query_id multiple time, as the call will
136  * be ignored if the top level query_id has already been reported.
137  */
138  pgstat_report_query_id(queryDesc->plannedstmt->queryId, false);
139 
140  if (ExecutorStart_hook)
141  (*ExecutorStart_hook) (queryDesc, eflags);
142  else
143  standard_ExecutorStart(queryDesc, eflags);
144 }
void standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:147
ExecutorStart_hook_type ExecutorStart_hook
Definition: execMain.c:71
void pgstat_report_query_id(uint64 query_id, bool force)
uint64 queryId
Definition: plannodes.h:48
PlannedStmt * plannedstmt
Definition: execdesc.h:37

◆ ExecWithCheckOptions()

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

Definition at line 1954 of file execMain.c.

References bms_union(), build_attrmap_by_name_if_req(), ExprContext::ecxt_scantuple, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecBuildSlotValueDescription(), ExecGetInsertedCols(), ExecGetUpdatedCols(), ExecQual(), execute_attr_map_slot(), forboth, GetPerTupleExprContext, WithCheckOption::kind, lfirst, MakeTupleTableSlot(), ExprEvalStep::map, WithCheckOption::polname, RelationGetDescr, RelationGetRelid, WithCheckOption::relname, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, ResultRelInfo::ri_WithCheckOptionExprs, ResultRelInfo::ri_WithCheckOptions, TTSOpsVirtual, ExprEvalStep::tupdesc, WCO_RLS_CONFLICT_CHECK, WCO_RLS_INSERT_CHECK, WCO_RLS_UPDATE_CHECK, and WCO_VIEW_CHECK.

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

1956 {
1957  Relation rel = resultRelInfo->ri_RelationDesc;
1958  TupleDesc tupdesc = RelationGetDescr(rel);
1959  ExprContext *econtext;
1960  ListCell *l1,
1961  *l2;
1962 
1963  /*
1964  * We will use the EState's per-tuple context for evaluating constraint
1965  * expressions (creating it if it's not already there).
1966  */
1967  econtext = GetPerTupleExprContext(estate);
1968 
1969  /* Arrange for econtext's scan tuple to be the tuple under test */
1970  econtext->ecxt_scantuple = slot;
1971 
1972  /* Check each of the constraints */
1973  forboth(l1, resultRelInfo->ri_WithCheckOptions,
1974  l2, resultRelInfo->ri_WithCheckOptionExprs)
1975  {
1976  WithCheckOption *wco = (WithCheckOption *) lfirst(l1);
1977  ExprState *wcoExpr = (ExprState *) lfirst(l2);
1978 
1979  /*
1980  * Skip any WCOs which are not the kind we are looking for at this
1981  * time.
1982  */
1983  if (wco->kind != kind)
1984  continue;
1985 
1986  /*
1987  * WITH CHECK OPTION checks are intended to ensure that the new tuple
1988  * is visible (in the case of a view) or that it passes the
1989  * 'with-check' policy (in the case of row security). If the qual
1990  * evaluates to NULL or FALSE, then the new tuple won't be included in
1991  * the view or doesn't pass the 'with-check' policy for the table.
1992  */
1993  if (!ExecQual(wcoExpr, econtext))
1994  {
1995  char *val_desc;
1996  Bitmapset *modifiedCols;
1997 
1998  switch (wco->kind)
1999  {
2000  /*
2001  * For WITH CHECK OPTIONs coming from views, we might be
2002  * able to provide the details on the row, depending on
2003  * the permissions on the relation (that is, if the user
2004  * could view it directly anyway). For RLS violations, we
2005  * don't include the data since we don't know if the user
2006  * should be able to view the tuple as that depends on the
2007  * USING policy.
2008  */
2009  case WCO_VIEW_CHECK:
2010  /* See the comment in ExecConstraints(). */
2011  if (resultRelInfo->ri_RootResultRelInfo)
2012  {
2013  ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2014  TupleDesc old_tupdesc = RelationGetDescr(rel);
2015  AttrMap *map;
2016 
2017  tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2018  /* a reverse map */
2019  map = build_attrmap_by_name_if_req(old_tupdesc,
2020  tupdesc);
2021 
2022  /*
2023  * Partition-specific slot's tupdesc can't be changed,
2024  * so allocate a new one.
2025  */
2026  if (map != NULL)
2027  slot = execute_attr_map_slot(map, slot,
2028  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
2029 
2030  modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
2031  ExecGetUpdatedCols(rootrel, estate));
2032  rel = rootrel->ri_RelationDesc;
2033  }
2034  else
2035  modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2036  ExecGetUpdatedCols(resultRelInfo, estate));
2038  slot,
2039  tupdesc,
2040  modifiedCols,
2041  64);
2042 
2043  ereport(ERROR,
2044  (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),
2045  errmsg("new row violates check option for view \"%s\"",
2046  wco->relname),
2047  val_desc ? errdetail("Failing row contains %s.",
2048  val_desc) : 0));
2049  break;
2050  case WCO_RLS_INSERT_CHECK:
2051  case WCO_RLS_UPDATE_CHECK:
2052  if (wco->polname != NULL)
2053  ereport(ERROR,
2054  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2055  errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
2056  wco->polname, wco->relname)));
2057  else
2058  ereport(ERROR,
2059  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2060  errmsg("new row violates row-level security policy for table \"%s\"",
2061  wco->relname)));
2062  break;
2064  if (wco->polname != NULL)
2065  ereport(ERROR,
2066  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2067  errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2068  wco->polname, wco->relname)));
2069  else
2070  ereport(ERROR,
2071  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2072  errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
2073  wco->relname)));
2074  break;
2075  default:
2076  elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
2077  break;
2078  }
2079  }
2080  }
2081 }
Relation ri_RelationDesc
Definition: execnodes.h:411
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
#define RelationGetDescr(relation)
Definition: rel.h:495
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1295
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:395
Definition: attmap.h:34
List * ri_WithCheckOptionExprs
Definition: execnodes.h:473
#define GetPerTupleExprContext(estate)
Definition: executor.h:532
AttrMap * build_attrmap_by_name_if_req(TupleDesc indesc, TupleDesc outdesc)
Definition: attmap.c:259
#define ERROR
Definition: elog.h:46
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2103
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:511
int errdetail(const char *fmt,...)
Definition: elog.c:1042
List * ri_WithCheckOptions
Definition: execnodes.h:470
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1112
#define ereport(elevel,...)
Definition: elog.h:157
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
#define lfirst(lc)
Definition: pg_list.h:169
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:225
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1256
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define RelationGetRelid(relation)
Definition: rel.h:469

◆ InitPlan()

static void InitPlan ( QueryDesc queryDesc,
int  eflags 
)
static

Definition at line 803 of file execMain.c.

References Assert, bms_is_member(), CheckValidRowMarkRel(), CMD_SELECT, ExecRowMark::curCtid, elog, ExecRowMark::ermActive, ExecRowMark::ermExtra, ERROR, EState::es_epq_active, EState::es_junkFilter, EState::es_plannedstmt, EState::es_range_table_size, EState::es_rowmarks, EState::es_subplanstates, EState::es_tupleTable, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_REWIND, EXEC_FLAG_WITH_NO_DATA, exec_rt_fetch(), ExecCheckRTPerms(), ExecGetRangeTableRelation(), ExecGetResultType(), ExecInitExtraTupleSlot(), ExecInitJunkFilter(), ExecInitNode(), ExecInitRangeTable(), i, PlanRowMark::isParent, ItemPointerSetInvalid, JunkFilter::jf_cleanTupType, lappend(), lfirst, ExecRowMark::markType, PlanRowMark::markType, NIL, QueryDesc::operation, palloc(), palloc0(), PlanState::plan, QueryDesc::plannedstmt, QueryDesc::planstate, PlannedStmt::planTree, ExecRowMark::prti, PlanRowMark::prti, ExecRowMark::relation, ExecRowMark::relid, RangeTblEntry::relid, TargetEntry::resjunk, PlannedStmt::rewindPlanIDs, ROW_MARK_COPY, ROW_MARK_EXCLUSIVE, ROW_MARK_KEYSHARE, ROW_MARK_NOKEYEXCLUSIVE, ROW_MARK_REFERENCE, ROW_MARK_SHARE, ExecRowMark::rowmarkId, PlanRowMark::rowmarkId, PlannedStmt::rowMarks, PlannedStmt::rtable, ExecRowMark::rti, PlanRowMark::rti, ExecRowMark::strength, PlanRowMark::strength, ExprEvalStep::subplan, PlannedStmt::subplans, Plan::targetlist, TTSOpsVirtual, 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  ExecInitRangeTable(estate, rangeTable);
824 
825  estate->es_plannedstmt = plannedstmt;
826 
827  /*
828  * Next, build the ExecRowMark array from the PlanRowMark(s), if any.
829  */
830  if (plannedstmt->rowMarks)
831  {
832  estate->es_rowmarks = (ExecRowMark **)
833  palloc0(estate->es_range_table_size * sizeof(ExecRowMark *));
834  foreach(l, plannedstmt->rowMarks)
835  {
836  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
837  Oid relid;
838  Relation relation;
839  ExecRowMark *erm;
840 
841  /* ignore "parent" rowmarks; they are irrelevant at runtime */
842  if (rc->isParent)
843  continue;
844 
845  /* get relation's OID (will produce InvalidOid if subquery) */
846  relid = exec_rt_fetch(rc->rti, estate)->relid;
847 
848  /* open relation, if we need to access it for this mark type */
849  switch (rc->markType)
850  {
851  case ROW_MARK_EXCLUSIVE:
853  case ROW_MARK_SHARE:
854  case ROW_MARK_KEYSHARE:
855  case ROW_MARK_REFERENCE:
856  relation = ExecGetRangeTableRelation(estate, rc->rti);
857  break;
858  case ROW_MARK_COPY:
859  /* no physical table access is required */
860  relation = NULL;
861  break;
862  default:
863  elog(ERROR, "unrecognized markType: %d", rc->markType);
864  relation = NULL; /* keep compiler quiet */
865  break;
866  }
867 
868  /* Check that relation is a legal target for marking */
869  if (relation)
870  CheckValidRowMarkRel(relation, rc->markType);
871 
872  erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
873  erm->relation = relation;
874  erm->relid = relid;
875  erm->rti = rc->rti;
876  erm->prti = rc->prti;
877  erm->rowmarkId = rc->rowmarkId;
878  erm->markType = rc->markType;
879  erm->strength = rc->strength;
880  erm->waitPolicy = rc->waitPolicy;
881  erm->ermActive = false;
883  erm->ermExtra = NULL;
884 
885  Assert(erm->rti > 0 && erm->rti <= estate->es_range_table_size &&
886  estate->es_rowmarks[erm->rti - 1] == NULL);
887 
888  estate->es_rowmarks[erm->rti - 1] = erm;
889  }
890  }
891 
892  /*
893  * Initialize the executor's tuple table to empty.
894  */
895  estate->es_tupleTable = NIL;
896 
897  /* signal that this EState is not used for EPQ */
898  estate->es_epq_active = NULL;
899 
900  /*
901  * Initialize private state information for each SubPlan. We must do this
902  * before running ExecInitNode on the main query tree, since
903  * ExecInitSubPlan expects to be able to find these entries.
904  */
905  Assert(estate->es_subplanstates == NIL);
906  i = 1; /* subplan indices count from 1 */
907  foreach(l, plannedstmt->subplans)
908  {
909  Plan *subplan = (Plan *) lfirst(l);
910  PlanState *subplanstate;
911  int sp_eflags;
912 
913  /*
914  * A subplan will never need to do BACKWARD scan nor MARK/RESTORE. If
915  * it is a parameterless subplan (not initplan), we suggest that it be
916  * prepared to handle REWIND efficiently; otherwise there is no need.
917  */
918  sp_eflags = eflags
920  if (bms_is_member(i, plannedstmt->rewindPlanIDs))
921  sp_eflags |= EXEC_FLAG_REWIND;
922 
923  subplanstate = ExecInitNode(subplan, estate, sp_eflags);
924 
925  estate->es_subplanstates = lappend(estate->es_subplanstates,
926  subplanstate);
927 
928  i++;
929  }
930 
931  /*
932  * Initialize the private state information for all the nodes in the query
933  * tree. This opens files, allocates storage and leaves us ready to start
934  * processing tuples.
935  */
936  planstate = ExecInitNode(plan, estate, eflags);
937 
938  /*
939  * Get the tuple descriptor describing the type of tuples to return.
940  */
941  tupType = ExecGetResultType(planstate);
942 
943  /*
944  * Initialize the junk filter if needed. SELECT queries need a filter if
945  * there are any junk attrs in the top-level tlist.
946  */
947  if (operation == CMD_SELECT)
948  {
949  bool junk_filter_needed = false;
950  ListCell *tlist;
951 
952  foreach(tlist, plan->targetlist)
953  {
954  TargetEntry *tle = (TargetEntry *) lfirst(tlist);
955 
956  if (tle->resjunk)
957  {
958  junk_filter_needed = true;
959  break;
960  }
961  }
962 
963  if (junk_filter_needed)
964  {
965  JunkFilter *j;
966  TupleTableSlot *slot;
967 
968  slot = ExecInitExtraTupleSlot(estate, NULL, &TTSOpsVirtual);
969  j = ExecInitJunkFilter(planstate->plan->targetlist,
970  slot);
971  estate->es_junkFilter = j;
972 
973  /* Want to return the cleaned tuple type */
974  tupType = j->jf_cleanTupType;
975  }
976  }
977 
978  queryDesc->tupDesc = tupType;
979  queryDesc->planstate = planstate;
980 }
#define NIL
Definition: pg_list.h:65
void ExecInitRangeTable(EState *estate, List *rangeTable)
Definition: execUtils.c:751
JunkFilter * es_junkFilter
Definition: execnodes.h:567
RowMarkType markType
Definition: plannodes.h:1120
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1831
EState * estate
Definition: execdesc.h:48
Relation relation
Definition: execnodes.h:670
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
PlannedStmt * es_plannedstmt
Definition: execnodes.h:564
bool ermActive
Definition: execnodes.h:678
Index prti
Definition: plannodes.h:1118
LockWaitPolicy waitPolicy
Definition: execnodes.h:677
#define EXEC_FLAG_WITH_NO_DATA
Definition: executor.h:61
LockClauseStrength strength
Definition: execnodes.h:676
unsigned int Oid
Definition: postgres_ext.h:31
Index rowmarkId
Definition: plannodes.h:1119
LockWaitPolicy waitPolicy
Definition: plannodes.h:1123
static void CheckValidRowMarkRel(Relation rel, RowMarkType markType)
Definition: execMain.c:1128
struct EPQState * es_epq_active
Definition: execnodes.h:627
struct Plan * planTree
Definition: plannodes.h:64
ItemPointerData curCtid
Definition: execnodes.h:679
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:562
bool resjunk
Definition: primnodes.h:1451
#define ERROR
Definition: elog.h:46
PlanState * planstate
Definition: execdesc.h:49
Index rti
Definition: execnodes.h:672
void * ermExtra
Definition: execnodes.h:680
TupleDesc jf_cleanTupType
Definition: execnodes.h:366
Index prti
Definition: execnodes.h:673
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:570
#define EXEC_FLAG_REWIND
Definition: executor.h:57
Index rowmarkId
Definition: execnodes.h:674
List * lappend(List *list, void *datum)
Definition: list.c:336
TupleDesc tupDesc
Definition: execdesc.h:47
CmdType operation
Definition: execdesc.h:36
List * es_tupleTable
Definition: execnodes.h:600
void * palloc0(Size size)
Definition: mcxt.c:1093
List * rowMarks
Definition: plannodes.h:78
Plan * plan
Definition: execnodes.h:964
Relation ExecGetRangeTableRelation(EState *estate, Index rti)
Definition: execUtils.c:782
List * subplans
Definition: plannodes.h:73
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Bitmapset * rewindPlanIDs
Definition: plannodes.h:76
RowMarkType markType
Definition: execnodes.h:675
LockClauseStrength strength
Definition: plannodes.h:1122
Index es_range_table_size
Definition: execnodes.h:559
List * es_subplanstates
Definition: execnodes.h:610
List * rtable
Definition: plannodes.h:66
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:490
List * targetlist
Definition: plannodes.h:141
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
int i
bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
Definition: execMain.c:568
bool isParent
Definition: plannodes.h:1124
PlannedStmt * plannedstmt
Definition: execdesc.h:37
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:141
Definition: pg_list.h:50
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56
JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
Definition: execJunk.c:60
CmdType
Definition: nodes.h:682

◆ InitResultRelInfo()

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

Definition at line 1193 of file execMain.c.

References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), MemSet, NIL, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, ResultRelInfo::ri_ChildToRootMap, ResultRelInfo::ri_ChildToRootMapValid, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_GeneratedExprs, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_newTupleSlot, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_oldTupleSlot, ResultRelInfo::ri_onConflict, ResultRelInfo::ri_onConflictArbiterIndexes, ResultRelInfo::ri_PartitionTupleSlot, ResultRelInfo::ri_projectNew, ResultRelInfo::ri_projectNewInfoValid, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RangeTableIndex, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_ReturningSlot, ResultRelInfo::ri_RootResultRelInfo, ResultRelInfo::ri_RootToPartitionMap, ResultRelInfo::ri_RowIdAttNo, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, ResultRelInfo::ri_TrigNewSlot, ResultRelInfo::ri_TrigOldSlot, ResultRelInfo::ri_TrigWhenExprs, ResultRelInfo::ri_usesFdwDirectModify, T_ResultRelInfo, RelationData::trigdesc, and ResultRelInfo::type.

Referenced by create_estate_for_relation(), ExecGetJunkAttribute(), ExecGetTriggerResultRel(), ExecInitPartitionDispatchInfo(), ExecInitPartitionInfo(), ExecInitResultRelation(), and ExecuteTruncateGuts().

1198 {
1199  MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1200  resultRelInfo->type = T_ResultRelInfo;
1201  resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1202  resultRelInfo->ri_RelationDesc = resultRelationDesc;
1203  resultRelInfo->ri_NumIndices = 0;
1204  resultRelInfo->ri_IndexRelationDescs = NULL;
1205  resultRelInfo->ri_IndexRelationInfo = NULL;
1206  /* make a copy so as not to depend on relcache info not changing... */
1207  resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1208  if (resultRelInfo->ri_TrigDesc)
1209  {
1210  int n = resultRelInfo->ri_TrigDesc->numtriggers;
1211 
1212  resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1213  palloc0(n * sizeof(FmgrInfo));
1214  resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1215  palloc0(n * sizeof(ExprState *));
1216  if (instrument_options)
1217  resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options);
1218  }
1219  else
1220  {
1221  resultRelInfo->ri_TrigFunctions = NULL;
1222  resultRelInfo->ri_TrigWhenExprs = NULL;
1223  resultRelInfo->ri_TrigInstrument = NULL;
1224  }
1225  if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1226  resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
1227  else
1228  resultRelInfo->ri_FdwRoutine = NULL;
1229 
1230  /* The following fields are set later if needed */
1231  resultRelInfo->ri_RowIdAttNo = 0;
1232  resultRelInfo->ri_projectNew = NULL;
1233  resultRelInfo->ri_newTupleSlot = NULL;
1234  resultRelInfo->ri_oldTupleSlot = NULL;
1235  resultRelInfo->ri_projectNewInfoValid = false;
1236  resultRelInfo->ri_FdwState = NULL;
1237  resultRelInfo->ri_usesFdwDirectModify = false;
1238  resultRelInfo->ri_ConstraintExprs = NULL;
1239  resultRelInfo->ri_GeneratedExprs = NULL;
1240  resultRelInfo->ri_projectReturning = NULL;
1241  resultRelInfo->ri_onConflictArbiterIndexes = NIL;
1242  resultRelInfo->ri_onConflict = NULL;
1243  resultRelInfo->ri_ReturningSlot = NULL;
1244  resultRelInfo->ri_TrigOldSlot = NULL;
1245  resultRelInfo->ri_TrigNewSlot = NULL;
1246 
1247  /*
1248  * Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
1249  * non-NULL partition_root_rri. For child relations that are part of the
1250  * initial query rather than being dynamically added by tuple routing,
1251  * this field is filled in ExecInitModifyTable().
1252  */
1253  resultRelInfo->ri_RootResultRelInfo = partition_root_rri;
1254  resultRelInfo->ri_RootToPartitionMap = NULL; /* set by
1255  * ExecInitRoutingInfo */
1256  resultRelInfo->ri_PartitionTupleSlot = NULL; /* ditto */
1257  resultRelInfo->ri_ChildToRootMap = NULL;
1258  resultRelInfo->ri_ChildToRootMapValid = false;
1259  resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
1260 }
int ri_NumIndices
Definition: execnodes.h:414
#define NIL
Definition: pg_list.h:65
Definition: fmgr.h:56
Relation ri_RelationDesc
Definition: execnodes.h:411
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:525
ProjectionInfo * ri_projectNew
Definition: execnodes.h:429
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:447
TupleConversionMap * ri_ChildToRootMap
Definition: execnodes.h:521
Instrumentation * InstrAlloc(int n, int instrument_options)
Definition: instrument.c:31
#define MemSet(start, val, len)
Definition: c.h:1008
Form_pg_class rd_rel
Definition: rel.h:109
TupleTableSlot * ri_TrigNewSlot
Definition: execnodes.h:452
bool ri_projectNewInfoValid
Definition: execnodes.h:435
Index ri_RangeTableIndex
Definition: execnodes.h:408
TupleTableSlot * ri_newTupleSlot
Definition: execnodes.h:431
NodeTag type
Definition: execnodes.h:405
bool ri_ChildToRootMapValid
Definition: execnodes.h:522
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:513
TriggerDesc * trigdesc
Definition: rel.h:115
bool ri_usesFdwDirectModify
Definition: execnodes.h:461
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:511
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:444
TupleTableSlot * ri_ReturningSlot
Definition: execnodes.h:450
ExprState ** ri_GeneratedExprs
Definition: execnodes.h:479
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:488
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:455
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:476
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:438
int numtriggers
Definition: reltrigger.h:50
OnConflictSetState * ri_onConflict
Definition: execnodes.h:494
void * palloc0(Size size)
Definition: mcxt.c:1093
void * ri_FdwState
Definition: execnodes.h:458
AttrNumber ri_RowIdAttNo
Definition: execnodes.h:426
TupleTableSlot * ri_TrigOldSlot
Definition: execnodes.h:451
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:1865
TupleTableSlot * ri_oldTupleSlot
Definition: execnodes.h:433
TupleConversionMap * ri_RootToPartitionMap
Definition: execnodes.h:512
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:427
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:420
List * ri_onConflictArbiterIndexes
Definition: execnodes.h:491
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:417
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:441

◆ 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 ExecGetJunkAttribute(), 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:557
Snapshot es_snapshot
Definition: execnodes.h:556
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
MemoryContext es_query_cxt
Definition: execnodes.h:598
PlanState * planstate
Definition: execdesc.h:49
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:852
TupleDesc tupDesc
Definition: execdesc.h:47
bool es_finished
Definition: execnodes.h:606
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:804
static void ExecEndPlan(PlanState *planstate, EState *estate)
Definition: execMain.c:1400
int es_top_eflags
Definition: execnodes.h:604
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56

◆ 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 ExecGetJunkAttribute(), 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:83
static void ExecPostprocessPlan(EState *estate)
Definition: execMain.c:1354
EState * estate
Definition: execdesc.h:48
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:598
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:67
bool es_finished
Definition: execnodes.h:606
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:804
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:60
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4539
int es_top_eflags
Definition: execnodes.h:604
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56

◆ standard_ExecutorRun()

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

Definition at line 309 of file execMain.c.

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

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

311 {
312  EState *estate;
313  CmdType operation;
315  bool sendTuples;
316  MemoryContext oldcontext;
317 
318  /* sanity checks */
319  Assert(queryDesc != NULL);
320 
321  estate = queryDesc->estate;
322 
323  Assert(estate != NULL);
325 
326  /*
327  * Switch into per-query memory context
328  */
329  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
330 
331  /* Allow instrumentation of Executor overall runtime */
332  if (queryDesc->totaltime)
333  InstrStartNode(queryDesc->totaltime);
334 
335  /*
336  * extract information from the query descriptor and the query feature.
337  */
338  operation = queryDesc->operation;
339  dest = queryDesc->dest;
340 
341  /*
342  * startup tuple receiver, if we will be emitting tuples
343  */
344  estate->es_processed = 0;
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:83
EState * estate
Definition: execdesc.h:48
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:48
MemoryContext es_query_cxt
Definition: execnodes.h:598
#define ERROR
Definition: elog.h:46
PlanState * planstate
Definition: execdesc.h:49
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:67
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:122
bool hasReturning
Definition: plannodes.h:50
TupleDesc tupDesc
Definition: execdesc.h:47
CmdType operation
Definition: execdesc.h:36
bool already_executed
Definition: execdesc.h:52
struct Instrumentation * totaltime
Definition: execdesc.h:55
#define Assert(condition)
Definition: c.h:804
uint64 es_processed
Definition: execnodes.h:602
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:125
DestReceiver * dest
Definition: execdesc.h:41
int es_top_eflags
Definition: execnodes.h:604
bool parallelModeNeeded
Definition: plannodes.h:60
#define elog(elevel,...)
Definition: elog.h:232
PlannedStmt * plannedstmt
Definition: execdesc.h:37
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56
CmdType
Definition: nodes.h:682
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:1506

◆ standard_ExecutorStart()

void standard_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 147 of file execMain.c.

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

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

148 {
149  EState *estate;
150  MemoryContext oldcontext;
151 
152  /* sanity checks: queryDesc must not be started already */
153  Assert(queryDesc != NULL);
154  Assert(queryDesc->estate == NULL);
155 
156  /*
157  * If the transaction is read-only, we need to check if any writes are
158  * planned to non-temporary tables. EXPLAIN is considered read-only.
159  *
160  * Don't allow writes in parallel mode. Supporting UPDATE and DELETE
161  * would require (a) storing the combo CID hash in shared memory, rather
162  * than synchronizing it just once at the start of parallelism, and (b) an
163  * alternative to heap_update()'s reliance on xmax for mutual exclusion.
164  * INSERT may have no such troubles, but we forbid it to simplify the
165  * checks.
166  *
167  * We have lower-level defenses in CommandCounterIncrement and elsewhere
168  * against performing unsafe operations in parallel mode, but this gives a
169  * more user-friendly error message.
170  */
171  if ((XactReadOnly || IsInParallelMode()) &&
172  !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
174 
175  /*
176  * Build EState, switch into per-query memory context for startup.
177  */
178  estate = CreateExecutorState();
179  queryDesc->estate = estate;
180 
181  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
182 
183  /*
184  * Fill in external parameters, if any, from queryDesc; and allocate
185  * workspace for internal parameters
186  */
187  estate->es_param_list_info = queryDesc->params;
188 
189  if (queryDesc->plannedstmt->paramExecTypes != NIL)
190  {
191  int nParamExec;
192 
193  nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes);
194  estate->es_param_exec_vals = (ParamExecData *)
195  palloc0(nParamExec * sizeof(ParamExecData));
196  }
197 
198  /* We now require all callers to provide sourceText */
199  Assert(queryDesc->sourceText != NULL);
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  estate->es_jit_flags = queryDesc->plannedstmt->jitFlags;
252 
253  /*
254  * Set up an AFTER-trigger statement context, unless told not to, or
255  * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called).
256  */
257  if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY)))
259 
260  /*
261  * Initialize the plan state tree
262  */
263  InitPlan(queryDesc, eflags);
264 
265  MemoryContextSwitchTo(oldcontext);
266 }
List * paramExecTypes
Definition: plannodes.h:84
#define NIL
Definition: pg_list.h:65
EState * estate
Definition: execdesc.h:48
CommandId es_output_cid
Definition: execnodes.h:570
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:810
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:557
Snapshot es_snapshot
Definition: execnodes.h:556
Snapshot snapshot
Definition: execdesc.h:39
int instrument_options
Definition: execdesc.h:44
const char * es_sourceText
Definition: execnodes.h:565
ParamExecData * es_param_exec_vals
Definition: execnodes.h:593
QueryEnvironment * queryEnv
Definition: execdesc.h:43
MemoryContext es_query_cxt
Definition: execnodes.h:598
bool IsInParallelMode(void)
Definition: xact.c:1012
#define ERROR
Definition: elog.h:46
int es_jit_flags
Definition: execnodes.h:643
ParamListInfo params
Definition: execdesc.h:42
int jitFlags
Definition: plannodes.h:62
int es_instrument
Definition: execnodes.h:605
EState * CreateExecutorState(void)
Definition: execUtils.c:90
QueryEnvironment * es_queryEnv
Definition: execnodes.h:595
CmdType operation
Definition: execdesc.h:36
static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
Definition: execMain.c:766
void * palloc0(Size size)
Definition: mcxt.c:1093
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
List * rowMarks
Definition: plannodes.h:78
bool XactReadOnly
Definition: xact.c:78
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4519
#define Assert(condition)
Definition: c.h:804
bool hasModifyingCTE
Definition: plannodes.h:52
static int list_length(const List *l)
Definition: pg_list.h:149
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:60
const char * sourceText
Definition: execdesc.h:38
int es_top_eflags
Definition: execnodes.h:604
#define elog(elevel,...)
Definition: elog.h:232
ParamListInfo es_param_list_info
Definition: execnodes.h:592
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:761
PlannedStmt * plannedstmt
Definition: execdesc.h:37
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56
static void InitPlan(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:803

Variable Documentation

◆ ExecutorCheckPerms_hook

ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL

Definition at line 77 of file execMain.c.

Referenced by _PG_init(), and ExecCheckRTPerms().

◆ ExecutorEnd_hook

ExecutorEnd_hook_type ExecutorEnd_hook = NULL

Definition at line 74 of file execMain.c.

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

◆ ExecutorFinish_hook

ExecutorFinish_hook_type ExecutorFinish_hook = NULL

Definition at line 73 of file execMain.c.

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

◆ ExecutorRun_hook

ExecutorRun_hook_type ExecutorRun_hook = NULL

Definition at line 72 of file execMain.c.

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

◆ ExecutorStart_hook

ExecutorStart_hook_type ExecutorStart_hook = NULL

Definition at line 71 of file execMain.c.

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