PostgreSQL Source Code git master
execMain.c File Reference
#include "postgres.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/tableam.h"
#include "access/xact.h"
#include "catalog/namespace.h"
#include "catalog/partition.h"
#include "commands/matview.h"
#include "commands/trigger.h"
#include "executor/executor.h"
#include "executor/nodeSubplan.h"
#include "foreign/fdwapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/queryjumble.h"
#include "parser/parse_relation.h"
#include "pgstat.h"
#include "rewrite/rewriteHandler.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/backend_status.h"
#include "utils/lsyscache.h"
#include "utils/partcache.h"
#include "utils/rls.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 (QueryDesc *queryDesc, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, DestReceiver *dest)
 
static bool ExecCheckOneRelPerms (RTEPermissionInfo *perminfo)
 
static bool ExecCheckPermissionsModified (Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms)
 
static void ExecCheckXactReadOnly (PlannedStmt *plannedstmt)
 
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)
 
void standard_ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, uint64 count)
 
void ExecutorFinish (QueryDesc *queryDesc)
 
void standard_ExecutorFinish (QueryDesc *queryDesc)
 
void ExecutorEnd (QueryDesc *queryDesc)
 
void standard_ExecutorEnd (QueryDesc *queryDesc)
 
void ExecutorRewind (QueryDesc *queryDesc)
 
bool ExecCheckPermissions (List *rangeTable, List *rteperminfos, bool ereport_on_violation)
 
void CheckValidResultRel (ResultRelInfo *resultRelInfo, CmdType operation, List *mergeActions)
 
void InitResultRelInfo (ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
 
ResultRelInfoExecGetTriggerResultRel (EState *estate, Oid relid, ResultRelInfo *rootRelInfo)
 
ListExecGetAncestorResultRels (EState *estate, ResultRelInfo *resultRelInfo)
 
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)
 
char * ExecBuildSlotValueDescription (Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
 
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, List *resultRelations)
 
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,
List mergeActions 
)

Definition at line 1026 of file execMain.c.

1028{
1029 Relation resultRel = resultRelInfo->ri_RelationDesc;
1030 FdwRoutine *fdwroutine;
1031
1032 /* Expect a fully-formed ResultRelInfo from InitResultRelInfo(). */
1033 Assert(resultRelInfo->ri_needLockTagTuple ==
1034 IsInplaceUpdateRelation(resultRel));
1035
1036 switch (resultRel->rd_rel->relkind)
1037 {
1038 case RELKIND_RELATION:
1039 case RELKIND_PARTITIONED_TABLE:
1040 CheckCmdReplicaIdentity(resultRel, operation);
1041 break;
1042 case RELKIND_SEQUENCE:
1043 ereport(ERROR,
1044 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1045 errmsg("cannot change sequence \"%s\"",
1046 RelationGetRelationName(resultRel))));
1047 break;
1048 case RELKIND_TOASTVALUE:
1049 ereport(ERROR,
1050 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1051 errmsg("cannot change TOAST relation \"%s\"",
1052 RelationGetRelationName(resultRel))));
1053 break;
1054 case RELKIND_VIEW:
1055
1056 /*
1057 * Okay only if there's a suitable INSTEAD OF trigger. Otherwise,
1058 * complain, but omit errdetail because we haven't got the
1059 * information handy (and given that it really shouldn't happen,
1060 * it's not worth great exertion to get).
1061 */
1062 if (!view_has_instead_trigger(resultRel, operation, mergeActions))
1063 error_view_not_updatable(resultRel, operation, mergeActions,
1064 NULL);
1065 break;
1066 case RELKIND_MATVIEW:
1068 ereport(ERROR,
1069 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1070 errmsg("cannot change materialized view \"%s\"",
1071 RelationGetRelationName(resultRel))));
1072 break;
1073 case RELKIND_FOREIGN_TABLE:
1074 /* Okay only if the FDW supports it */
1075 fdwroutine = resultRelInfo->ri_FdwRoutine;
1076 switch (operation)
1077 {
1078 case CMD_INSERT:
1079 if (fdwroutine->ExecForeignInsert == NULL)
1080 ereport(ERROR,
1081 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1082 errmsg("cannot insert into foreign table \"%s\"",
1083 RelationGetRelationName(resultRel))));
1084 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1085 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1086 ereport(ERROR,
1087 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1088 errmsg("foreign table \"%s\" does not allow inserts",
1089 RelationGetRelationName(resultRel))));
1090 break;
1091 case CMD_UPDATE:
1092 if (fdwroutine->ExecForeignUpdate == NULL)
1093 ereport(ERROR,
1094 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1095 errmsg("cannot update foreign table \"%s\"",
1096 RelationGetRelationName(resultRel))));
1097 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1098 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1099 ereport(ERROR,
1100 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1101 errmsg("foreign table \"%s\" does not allow updates",
1102 RelationGetRelationName(resultRel))));
1103 break;
1104 case CMD_DELETE:
1105 if (fdwroutine->ExecForeignDelete == NULL)
1106 ereport(ERROR,
1107 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1108 errmsg("cannot delete from foreign table \"%s\"",
1109 RelationGetRelationName(resultRel))));
1110 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1111 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1112 ereport(ERROR,
1113 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1114 errmsg("foreign table \"%s\" does not allow deletes",
1115 RelationGetRelationName(resultRel))));
1116 break;
1117 default:
1118 elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1119 break;
1120 }
1121 break;
1122 default:
1123 ereport(ERROR,
1124 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1125 errmsg("cannot change relation \"%s\"",
1126 RelationGetRelationName(resultRel))));
1127 break;
1128 }
1129}
#define Assert(condition)
Definition: c.h:815
bool IsInplaceUpdateRelation(Relation relation)
Definition: catalog.c:152
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition: matview.c:970
@ CMD_INSERT
Definition: nodes.h:267
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
#define RelationGetRelationName(relation)
Definition: rel.h:539
bool view_has_instead_trigger(Relation view, CmdType event, List *mergeActionList)
void error_view_not_updatable(Relation view, CmdType command, List *mergeActionList, const char *detail)
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:232
ExecForeignUpdate_function ExecForeignUpdate
Definition: fdwapi.h:235
ExecForeignDelete_function ExecForeignDelete
Definition: fdwapi.h:236
IsForeignRelUpdatable_function IsForeignRelUpdatable
Definition: fdwapi.h:240
Form_pg_class rd_rel
Definition: rel.h:111
bool ri_needLockTagTuple
Definition: execnodes.h:504
Relation ri_RelationDesc
Definition: execnodes.h:474
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:525

References Assert, CheckCmdReplicaIdentity(), CMD_DELETE, CMD_INSERT, CMD_UPDATE, elog, ereport, errcode(), errmsg(), ERROR, error_view_not_updatable(), FdwRoutine::ExecForeignDelete, FdwRoutine::ExecForeignInsert, FdwRoutine::ExecForeignUpdate, FdwRoutine::IsForeignRelUpdatable, IsInplaceUpdateRelation(), MatViewIncrementalMaintenanceIsEnabled(), RelationData::rd_rel, RelationGetRelationName, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_needLockTagTuple, ResultRelInfo::ri_RelationDesc, and view_has_instead_trigger().

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

◆ CheckValidRowMarkRel()

static void CheckValidRowMarkRel ( Relation  rel,
RowMarkType  markType 
)
static

Definition at line 1138 of file execMain.c.

1139{
1140 FdwRoutine *fdwroutine;
1141
1142 switch (rel->rd_rel->relkind)
1143 {
1144 case RELKIND_RELATION:
1145 case RELKIND_PARTITIONED_TABLE:
1146 /* OK */
1147 break;
1148 case RELKIND_SEQUENCE:
1149 /* Must disallow this because we don't vacuum sequences */
1150 ereport(ERROR,
1151 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1152 errmsg("cannot lock rows in sequence \"%s\"",
1154 break;
1155 case RELKIND_TOASTVALUE:
1156 /* We could allow this, but there seems no good reason to */
1157 ereport(ERROR,
1158 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1159 errmsg("cannot lock rows in TOAST relation \"%s\"",
1161 break;
1162 case RELKIND_VIEW:
1163 /* Should not get here; planner should have expanded the view */
1164 ereport(ERROR,
1165 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1166 errmsg("cannot lock rows in view \"%s\"",
1168 break;
1169 case RELKIND_MATVIEW:
1170 /* Allow referencing a matview, but not actual locking clauses */
1171 if (markType != ROW_MARK_REFERENCE)
1172 ereport(ERROR,
1173 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1174 errmsg("cannot lock rows in materialized view \"%s\"",
1176 break;
1177 case RELKIND_FOREIGN_TABLE:
1178 /* Okay only if the FDW supports it */
1179 fdwroutine = GetFdwRoutineForRelation(rel, false);
1180 if (fdwroutine->RefetchForeignRow == NULL)
1181 ereport(ERROR,
1182 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1183 errmsg("cannot lock rows in foreign table \"%s\"",
1185 break;
1186 default:
1187 ereport(ERROR,
1188 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1189 errmsg("cannot lock rows in relation \"%s\"",
1191 break;
1192 }
1193}
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:442
@ ROW_MARK_REFERENCE
Definition: plannodes.h:1333
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:248

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

Referenced by InitPlan().

◆ EvalPlanQual()

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

Definition at line 2484 of file execMain.c.

2486{
2487 TupleTableSlot *slot;
2488 TupleTableSlot *testslot;
2489
2490 Assert(rti > 0);
2491
2492 /*
2493 * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2494 */
2495 EvalPlanQualBegin(epqstate);
2496
2497 /*
2498 * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
2499 * an unnecessary copy.
2500 */
2501 testslot = EvalPlanQualSlot(epqstate, relation, rti);
2502 if (testslot != inputslot)
2503 ExecCopySlot(testslot, inputslot);
2504
2505 /*
2506 * Mark that an EPQ tuple is available for this relation. (If there is
2507 * more than one result relation, the others remain marked as having no
2508 * tuple available.)
2509 */
2510 epqstate->relsubs_done[rti - 1] = false;
2511 epqstate->relsubs_blocked[rti - 1] = false;
2512
2513 /*
2514 * Run the EPQ query. We assume it will return at most one tuple.
2515 */
2516 slot = EvalPlanQualNext(epqstate);
2517
2518 /*
2519 * If we got a tuple, force the slot to materialize the tuple so that it
2520 * is not dependent on any local state in the EPQ query (in particular,
2521 * it's highly likely that the slot contains references to any pass-by-ref
2522 * datums that may be present in copyTuple). As with the next step, this
2523 * is to guard against early re-use of the EPQ query.
2524 */
2525 if (!TupIsNull(slot))
2526 ExecMaterializeSlot(slot);
2527
2528 /*
2529 * Clear out the test tuple, and mark that no tuple is available here.
2530 * This is needed in case the EPQ state is re-used to test a tuple for a
2531 * different target relation.
2532 */
2533 ExecClearTuple(testslot);
2534 epqstate->relsubs_blocked[rti - 1] = true;
2535
2536 return slot;
2537}
TupleTableSlot * EvalPlanQualSlot(EPQState *epqstate, Relation relation, Index rti)
Definition: execMain.c:2612
void EvalPlanQualBegin(EPQState *epqstate)
Definition: execMain.c:2765
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition: execMain.c:2749
bool * relsubs_blocked
Definition: execnodes.h:1332
bool * relsubs_done
Definition: execnodes.h:1323
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454
#define TupIsNull(slot)
Definition: tuptable.h:306
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:509
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:472

References Assert, EvalPlanQualBegin(), EvalPlanQualNext(), EvalPlanQualSlot(), ExecClearTuple(), ExecCopySlot(), ExecMaterializeSlot(), EPQState::relsubs_blocked, EPQState::relsubs_done, and TupIsNull.

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2765 of file execMain.c.

2766{
2767 EState *parentestate = epqstate->parentestate;
2768 EState *recheckestate = epqstate->recheckestate;
2769
2770 if (recheckestate == NULL)
2771 {
2772 /* First time through, so create a child EState */
2773 EvalPlanQualStart(epqstate, epqstate->plan);
2774 }
2775 else
2776 {
2777 /*
2778 * We already have a suitable child EPQ tree, so just reset it.
2779 */
2780 Index rtsize = parentestate->es_range_table_size;
2781 PlanState *rcplanstate = epqstate->recheckplanstate;
2782
2783 /*
2784 * Reset the relsubs_done[] flags to equal relsubs_blocked[], so that
2785 * the EPQ run will never attempt to fetch tuples from blocked target
2786 * relations.
2787 */
2788 memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
2789 rtsize * sizeof(bool));
2790
2791 /* Recopy current values of parent parameters */
2792 if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2793 {
2794 int i;
2795
2796 /*
2797 * Force evaluation of any InitPlan outputs that could be needed
2798 * by the subplan, just in case they got reset since
2799 * EvalPlanQualStart (see comments therein).
2800 */
2801 ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2802 GetPerTupleExprContext(parentestate));
2803
2804 i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2805
2806 while (--i >= 0)
2807 {
2808 /* copy value if any, but not execPlan link */
2809 recheckestate->es_param_exec_vals[i].value =
2810 parentestate->es_param_exec_vals[i].value;
2811 recheckestate->es_param_exec_vals[i].isnull =
2812 parentestate->es_param_exec_vals[i].isnull;
2813 }
2814 }
2815
2816 /*
2817 * Mark child plan tree as needing rescan at all scan nodes. The
2818 * first ExecProcNode will take care of actually doing the rescan.
2819 */
2820 rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2821 epqstate->epqParam);
2822 }
2823}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
unsigned int Index
Definition: c.h:571
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition: execMain.c:2832
#define GetPerTupleExprContext(estate)
Definition: executor.h:563
int i
Definition: isn.c:72
void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext)
Definition: nodeSubplan.c:1276
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
Plan * plan
Definition: execnodes.h:1295
int epqParam
Definition: execnodes.h:1278
EState * parentestate
Definition: execnodes.h:1277
EState * recheckestate
Definition: execnodes.h:1309
PlanState * recheckplanstate
Definition: execnodes.h:1334
PlannedStmt * es_plannedstmt
Definition: execnodes.h:657
ParamExecData * es_param_exec_vals
Definition: execnodes.h:686
Index es_range_table_size
Definition: execnodes.h:651
bool isnull
Definition: params.h:150
Datum value
Definition: params.h:149
Plan * plan
Definition: execnodes.h:1141
Bitmapset * chgParam
Definition: execnodes.h:1173
Bitmapset * extParam
Definition: plannodes.h:171
List * paramExecTypes
Definition: plannodes.h:93

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(), NIL, PlannedStmt::paramExecTypes, EPQState::parentestate, PlanState::plan, EPQState::plan, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_blocked, EPQState::relsubs_done, and ParamExecData::value.

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2996 of file execMain.c.

2997{
2998 EState *estate = epqstate->recheckestate;
2999 Index rtsize;
3000 MemoryContext oldcontext;
3001 ListCell *l;
3002
3003 rtsize = epqstate->parentestate->es_range_table_size;
3004
3005 /*
3006 * We may have a tuple table, even if EPQ wasn't started, because we allow
3007 * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
3008 */
3009 if (epqstate->tuple_table != NIL)
3010 {
3011 memset(epqstate->relsubs_slot, 0,
3012 rtsize * sizeof(TupleTableSlot *));
3013 ExecResetTupleTable(epqstate->tuple_table, true);
3014 epqstate->tuple_table = NIL;
3015 }
3016
3017 /* EPQ wasn't started, nothing further to do */
3018 if (estate == NULL)
3019 return;
3020
3021 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3022
3023 ExecEndNode(epqstate->recheckplanstate);
3024
3025 foreach(l, estate->es_subplanstates)
3026 {
3027 PlanState *subplanstate = (PlanState *) lfirst(l);
3028
3029 ExecEndNode(subplanstate);
3030 }
3031
3032 /* throw away the per-estate tuple table, some node may have used it */
3033 ExecResetTupleTable(estate->es_tupleTable, false);
3034
3035 /* Close any result and trigger target relations attached to this EState */
3037
3038 MemoryContextSwitchTo(oldcontext);
3039
3040 FreeExecutorState(estate);
3041
3042 /* Mark EPQState idle */
3043 epqstate->origslot = NULL;
3044 epqstate->recheckestate = NULL;
3045 epqstate->recheckplanstate = NULL;
3046 epqstate->relsubs_rowmark = NULL;
3047 epqstate->relsubs_done = NULL;
3048 epqstate->relsubs_blocked = NULL;
3049}
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1524
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1378
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define lfirst(lc)
Definition: pg_list.h:172
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1316
TupleTableSlot * origslot
Definition: execnodes.h:1304
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1288
List * tuple_table
Definition: execnodes.h:1287
MemoryContext es_query_cxt
Definition: execnodes.h:691
List * es_tupleTable
Definition: execnodes.h:693
List * es_subplanstates
Definition: execnodes.h:706

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_blocked, 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(), ExecEndModifyTable(), and ExecLockRows().

◆ EvalPlanQualFetchRowMark()

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

Definition at line 2640 of file execMain.c.

2641{
2642 ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1];
2643 ExecRowMark *erm = earm->rowmark;
2644 Datum datum;
2645 bool isNull;
2646
2647 Assert(earm != NULL);
2648 Assert(epqstate->origslot != NULL);
2649
2651 elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2652
2653 /* if child rel, must check whether it produced this row */
2654 if (erm->rti != erm->prti)
2655 {
2656 Oid tableoid;
2657
2658 datum = ExecGetJunkAttribute(epqstate->origslot,
2659 earm->toidAttNo,
2660 &isNull);
2661 /* non-locked rels could be on the inside of outer joins */
2662 if (isNull)
2663 return false;
2664
2665 tableoid = DatumGetObjectId(datum);
2666
2667 Assert(OidIsValid(erm->relid));
2668 if (tableoid != erm->relid)
2669 {
2670 /* this child is inactive right now */
2671 return false;
2672 }
2673 }
2674
2675 if (erm->markType == ROW_MARK_REFERENCE)
2676 {
2677 Assert(erm->relation != NULL);
2678
2679 /* fetch the tuple's ctid */
2680 datum = ExecGetJunkAttribute(epqstate->origslot,
2681 earm->ctidAttNo,
2682 &isNull);
2683 /* non-locked rels could be on the inside of outer joins */
2684 if (isNull)
2685 return false;
2686
2687 /* fetch requests on foreign tables must be passed to their FDW */
2688 if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2689 {
2690 FdwRoutine *fdwroutine;
2691 bool updated = false;
2692
2693 fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2694 /* this should have been checked already, but let's be safe */
2695 if (fdwroutine->RefetchForeignRow == NULL)
2696 ereport(ERROR,
2697 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2698 errmsg("cannot lock rows in foreign table \"%s\"",
2700
2701 fdwroutine->RefetchForeignRow(epqstate->recheckestate,
2702 erm,
2703 datum,
2704 slot,
2705 &updated);
2706 if (TupIsNull(slot))
2707 elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2708
2709 /*
2710 * Ideally we'd insist on updated == false here, but that assumes
2711 * that FDWs can track that exactly, which they might not be able
2712 * to. So just ignore the flag.
2713 */
2714 return true;
2715 }
2716 else
2717 {
2718 /* ordinary table, fetch the tuple */
2721 SnapshotAny, slot))
2722 elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2723 return true;
2724 }
2725 }
2726 else
2727 {
2728 Assert(erm->markType == ROW_MARK_COPY);
2729
2730 /* fetch the whole-row Var for the relation */
2731 datum = ExecGetJunkAttribute(epqstate->origslot,
2732 earm->wholeAttNo,
2733 &isNull);
2734 /* non-locked rels could be on the inside of outer joins */
2735 if (isNull)
2736 return false;
2737
2738 ExecStoreHeapTupleDatum(datum, slot);
2739 return true;
2740 }
2741}
#define OidIsValid(objectId)
Definition: c.h:732
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
Definition: execTuples.c:1793
static Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: executor.h:184
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:1337
@ ROW_MARK_COPY
Definition: plannodes.h:1334
uintptr_t Datum
Definition: postgres.h:69
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:247
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
unsigned int Oid
Definition: postgres_ext.h:32
#define SnapshotAny
Definition: snapmgr.h:33
AttrNumber wholeAttNo
Definition: execnodes.h:805
ExecRowMark * rowmark
Definition: execnodes.h:802
AttrNumber toidAttNo
Definition: execnodes.h:804
AttrNumber ctidAttNo
Definition: execnodes.h:803
Index rti
Definition: execnodes.h:780
Index prti
Definition: execnodes.h:781
Relation relation
Definition: execnodes.h:778
RowMarkType markType
Definition: execnodes.h:783
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
Definition: tableam.h:1293

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

◆ EvalPlanQualInit()

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

Definition at line 2553 of file execMain.c.

2556{
2557 Index rtsize = parentestate->es_range_table_size;
2558
2559 /* initialize data not changing over EPQState's lifetime */
2560 epqstate->parentestate = parentestate;
2561 epqstate->epqParam = epqParam;
2562 epqstate->resultRelations = resultRelations;
2563
2564 /*
2565 * Allocate space to reference a slot for each potential rti - do so now
2566 * rather than in EvalPlanQualBegin(), as done for other dynamically
2567 * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2568 * that *may* need EPQ later, without forcing the overhead of
2569 * EvalPlanQualBegin().
2570 */
2571 epqstate->tuple_table = NIL;
2572 epqstate->relsubs_slot = (TupleTableSlot **)
2573 palloc0(rtsize * sizeof(TupleTableSlot *));
2574
2575 /* ... and remember data that EvalPlanQualBegin will need */
2576 epqstate->plan = subplan;
2577 epqstate->arowMarks = auxrowmarks;
2578
2579 /* ... and mark the EPQ state inactive */
2580 epqstate->origslot = NULL;
2581 epqstate->recheckestate = NULL;
2582 epqstate->recheckplanstate = NULL;
2583 epqstate->relsubs_rowmark = NULL;
2584 epqstate->relsubs_done = NULL;
2585 epqstate->relsubs_blocked = NULL;
2586}
void * palloc0(Size size)
Definition: mcxt.c:1347
List * resultRelations
Definition: execnodes.h:1279
List * arowMarks
Definition: execnodes.h:1296

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

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

◆ EvalPlanQualNext()

TupleTableSlot * EvalPlanQualNext ( EPQState epqstate)

Definition at line 2749 of file execMain.c.

2750{
2751 MemoryContext oldcontext;
2752 TupleTableSlot *slot;
2753
2754 oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2755 slot = ExecProcNode(epqstate->recheckplanstate);
2756 MemoryContextSwitchTo(oldcontext);
2757
2758 return slot;
2759}
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:267

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

Referenced by EvalPlanQual(), and ExecLockRows().

◆ EvalPlanQualSetPlan()

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

Definition at line 2595 of file execMain.c.

2596{
2597 /* If we have a live EPQ query, shut it down */
2598 EvalPlanQualEnd(epqstate);
2599 /* And set/change the plan pointer */
2600 epqstate->plan = subplan;
2601 /* The rowmarks depend on the plan, too */
2602 epqstate->arowMarks = auxrowmarks;
2603}
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2996

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2612 of file execMain.c.

2614{
2615 TupleTableSlot **slot;
2616
2617 Assert(relation);
2618 Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2619 slot = &epqstate->relsubs_slot[rti - 1];
2620
2621 if (*slot == NULL)
2622 {
2623 MemoryContext oldcontext;
2624
2625 oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2626 *slot = table_slot_create(relation, &epqstate->tuple_table);
2627 MemoryContextSwitchTo(oldcontext);
2628 }
2629
2630 return *slot;
2631}
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91

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

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

◆ EvalPlanQualStart()

static void EvalPlanQualStart ( EPQState epqstate,
Plan planTree 
)
static

Definition at line 2832 of file execMain.c.

2833{
2834 EState *parentestate = epqstate->parentestate;
2835 Index rtsize = parentestate->es_range_table_size;
2836 EState *rcestate;
2837 MemoryContext oldcontext;
2838 ListCell *l;
2839
2840 epqstate->recheckestate = rcestate = CreateExecutorState();
2841
2842 oldcontext = MemoryContextSwitchTo(rcestate->es_query_cxt);
2843
2844 /* signal that this is an EState for executing EPQ */
2845 rcestate->es_epq_active = epqstate;
2846
2847 /*
2848 * Child EPQ EStates share the parent's copy of unchanging state such as
2849 * the snapshot, rangetable, and external Param info. They need their own
2850 * copies of local state, including a tuple table, es_param_exec_vals,
2851 * result-rel info, etc.
2852 */
2854 rcestate->es_snapshot = parentestate->es_snapshot;
2855 rcestate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
2856 rcestate->es_range_table = parentestate->es_range_table;
2857 rcestate->es_range_table_size = parentestate->es_range_table_size;
2858 rcestate->es_relations = parentestate->es_relations;
2859 rcestate->es_rowmarks = parentestate->es_rowmarks;
2860 rcestate->es_rteperminfos = parentestate->es_rteperminfos;
2861 rcestate->es_plannedstmt = parentestate->es_plannedstmt;
2862 rcestate->es_junkFilter = parentestate->es_junkFilter;
2863 rcestate->es_output_cid = parentestate->es_output_cid;
2864 rcestate->es_queryEnv = parentestate->es_queryEnv;
2865
2866 /*
2867 * ResultRelInfos needed by subplans are initialized from scratch when the
2868 * subplans themselves are initialized.
2869 */
2870 rcestate->es_result_relations = NULL;
2871 /* es_trig_target_relations must NOT be copied */
2872 rcestate->es_top_eflags = parentestate->es_top_eflags;
2873 rcestate->es_instrument = parentestate->es_instrument;
2874 /* es_auxmodifytables must NOT be copied */
2875
2876 /*
2877 * The external param list is simply shared from parent. The internal
2878 * param workspace has to be local state, but we copy the initial values
2879 * from the parent, so as to have access to any param values that were
2880 * already set from other parts of the parent's plan tree.
2881 */
2882 rcestate->es_param_list_info = parentestate->es_param_list_info;
2883 if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2884 {
2885 int i;
2886
2887 /*
2888 * Force evaluation of any InitPlan outputs that could be needed by
2889 * the subplan. (With more complexity, maybe we could postpone this
2890 * till the subplan actually demands them, but it doesn't seem worth
2891 * the trouble; this is a corner case already, since usually the
2892 * InitPlans would have been evaluated before reaching EvalPlanQual.)
2893 *
2894 * This will not touch output params of InitPlans that occur somewhere
2895 * within the subplan tree, only those that are attached to the
2896 * ModifyTable node or above it and are referenced within the subplan.
2897 * That's OK though, because the planner would only attach such
2898 * InitPlans to a lower-level SubqueryScan node, and EPQ execution
2899 * will not descend into a SubqueryScan.
2900 *
2901 * The EState's per-output-tuple econtext is sufficiently short-lived
2902 * for this, since it should get reset before there is any chance of
2903 * doing EvalPlanQual again.
2904 */
2906 GetPerTupleExprContext(parentestate));
2907
2908 /* now make the internal param workspace ... */
2909 i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2910 rcestate->es_param_exec_vals = (ParamExecData *)
2911 palloc0(i * sizeof(ParamExecData));
2912 /* ... and copy down all values, whether really needed or not */
2913 while (--i >= 0)
2914 {
2915 /* copy value if any, but not execPlan link */
2916 rcestate->es_param_exec_vals[i].value =
2917 parentestate->es_param_exec_vals[i].value;
2918 rcestate->es_param_exec_vals[i].isnull =
2919 parentestate->es_param_exec_vals[i].isnull;
2920 }
2921 }
2922
2923 /*
2924 * Initialize private state information for each SubPlan. We must do this
2925 * before running ExecInitNode on the main query tree, since
2926 * ExecInitSubPlan expects to be able to find these entries. Some of the
2927 * SubPlans might not be used in the part of the plan tree we intend to
2928 * run, but since it's not easy to tell which, we just initialize them
2929 * all.
2930 */
2931 Assert(rcestate->es_subplanstates == NIL);
2932 foreach(l, parentestate->es_plannedstmt->subplans)
2933 {
2934 Plan *subplan = (Plan *) lfirst(l);
2935 PlanState *subplanstate;
2936
2937 subplanstate = ExecInitNode(subplan, rcestate, 0);
2938 rcestate->es_subplanstates = lappend(rcestate->es_subplanstates,
2939 subplanstate);
2940 }
2941
2942 /*
2943 * Build an RTI indexed array of rowmarks, so that
2944 * EvalPlanQualFetchRowMark() can efficiently access the to be fetched
2945 * rowmark.
2946 */
2947 epqstate->relsubs_rowmark = (ExecAuxRowMark **)
2948 palloc0(rtsize * sizeof(ExecAuxRowMark *));
2949 foreach(l, epqstate->arowMarks)
2950 {
2951 ExecAuxRowMark *earm = (ExecAuxRowMark *) lfirst(l);
2952
2953 epqstate->relsubs_rowmark[earm->rowmark->rti - 1] = earm;
2954 }
2955
2956 /*
2957 * Initialize per-relation EPQ tuple states. Result relations, if any,
2958 * get marked as blocked; others as not-fetched.
2959 */
2960 epqstate->relsubs_done = palloc_array(bool, rtsize);
2961 epqstate->relsubs_blocked = palloc0_array(bool, rtsize);
2962
2963 foreach(l, epqstate->resultRelations)
2964 {
2965 int rtindex = lfirst_int(l);
2966
2967 Assert(rtindex > 0 && rtindex <= rtsize);
2968 epqstate->relsubs_blocked[rtindex - 1] = true;
2969 }
2970
2971 memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
2972 rtsize * sizeof(bool));
2973
2974 /*
2975 * Initialize the private state information for all the nodes in the part
2976 * of the plan tree we need to run. This opens files, allocates storage
2977 * and leaves us ready to start processing tuples.
2978 */
2979 epqstate->recheckplanstate = ExecInitNode(planTree, rcestate, 0);
2980
2981 MemoryContextSwitchTo(oldcontext);
2982}
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define palloc_array(type, count)
Definition: fe_memutils.h:76
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
List * lappend(List *list, void *datum)
Definition: list.c:339
#define lfirst_int(lc)
Definition: pg_list.h:173
@ ForwardScanDirection
Definition: sdir.h:28
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:654
int es_top_eflags
Definition: execnodes.h:700
int es_instrument
Definition: execnodes.h:701
QueryEnvironment * es_queryEnv
Definition: execnodes.h:688
ResultRelInfo ** es_result_relations
Definition: execnodes.h:666
List * es_range_table
Definition: execnodes.h:650
List * es_rteperminfos
Definition: execnodes.h:656
ParamListInfo es_param_list_info
Definition: execnodes.h:685
ScanDirection es_direction
Definition: execnodes.h:647
struct EPQState * es_epq_active
Definition: execnodes.h:723
Relation * es_relations
Definition: execnodes.h:652
CommandId es_output_cid
Definition: execnodes.h:663
Snapshot es_snapshot
Definition: execnodes.h:648
JunkFilter * es_junkFilter
Definition: execnodes.h:660
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:649
List * subplans
Definition: plannodes.h:82

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_rteperminfos, EState::es_snapshot, EState::es_subplanstates, EState::es_top_eflags, ExecInitNode(), ExecSetParamPlanMulti(), Plan::extParam, ForwardScanDirection, GetPerTupleExprContext, i, ParamExecData::isnull, lappend(), lfirst, lfirst_int, list_length(), MemoryContextSwitchTo(), NIL, palloc0(), palloc0_array, palloc_array, PlannedStmt::paramExecTypes, EPQState::parentestate, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_blocked, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::resultRelations, ExecAuxRowMark::rowmark, ExecRowMark::rti, PlannedStmt::subplans, and ParamExecData::value.

Referenced by EvalPlanQualBegin().

◆ ExecBuildAuxRowMark()

ExecAuxRowMark * ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2414 of file execMain.c.

2415{
2417 char resname[32];
2418
2419 aerm->rowmark = erm;
2420
2421 /* Look up the resjunk columns associated with this rowmark */
2422 if (erm->markType != ROW_MARK_COPY)
2423 {
2424 /* need ctid for all methods other than COPY */
2425 snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2426 aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2427 resname);
2429 elog(ERROR, "could not find junk %s column", resname);
2430 }
2431 else
2432 {
2433 /* need wholerow if COPY */
2434 snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2435 aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2436 resname);
2438 elog(ERROR, "could not find junk %s column", resname);
2439 }
2440
2441 /* if child rel, need tableoid */
2442 if (erm->rti != erm->prti)
2443 {
2444 snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2445 aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2446 resname);
2448 elog(ERROR, "could not find junk %s column", resname);
2449 }
2450
2451 return aerm;
2452}
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:222
#define snprintf
Definition: port.h:238
Index rowmarkId
Definition: execnodes.h:782

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecBuildSlotValueDescription()

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

Definition at line 2228 of file execMain.c.

2233{
2235 StringInfoData collist;
2236 bool write_comma = false;
2237 bool write_comma_collist = false;
2238 int i;
2239 AclResult aclresult;
2240 bool table_perm = false;
2241 bool any_perm = false;
2242
2243 /*
2244 * Check if RLS is enabled and should be active for the relation; if so,
2245 * then don't return anything. Otherwise, go through normal permission
2246 * checks.
2247 */
2248 if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2249 return NULL;
2250
2252
2254
2255 /*
2256 * Check if the user has permissions to see the row. Table-level SELECT
2257 * allows access to all columns. If the user does not have table-level
2258 * SELECT then we check each column and include those the user has SELECT
2259 * rights on. Additionally, we always include columns the user provided
2260 * data for.
2261 */
2262 aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2263 if (aclresult != ACLCHECK_OK)
2264 {
2265 /* Set up the buffer for the column list */
2266 initStringInfo(&collist);
2267 appendStringInfoChar(&collist, '(');
2268 }
2269 else
2270 table_perm = any_perm = true;
2271
2272 /* Make sure the tuple is fully deconstructed */
2273 slot_getallattrs(slot);
2274
2275 for (i = 0; i < tupdesc->natts; i++)
2276 {
2277 bool column_perm = false;
2278 char *val;
2279 int vallen;
2280 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2281
2282 /* ignore dropped columns */
2283 if (att->attisdropped)
2284 continue;
2285
2286 if (!table_perm)
2287 {
2288 /*
2289 * No table-level SELECT, so need to make sure they either have
2290 * SELECT rights on the column or that they have provided the data
2291 * for the column. If not, omit this column from the error
2292 * message.
2293 */
2294 aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2297 modifiedCols) || aclresult == ACLCHECK_OK)
2298 {
2299 column_perm = any_perm = true;
2300
2301 if (write_comma_collist)
2302 appendStringInfoString(&collist, ", ");
2303 else
2304 write_comma_collist = true;
2305
2306 appendStringInfoString(&collist, NameStr(att->attname));
2307 }
2308 }
2309
2310 if (table_perm || column_perm)
2311 {
2312 if (slot->tts_isnull[i])
2313 val = "null";
2314 else
2315 {
2316 Oid foutoid;
2317 bool typisvarlena;
2318
2319 getTypeOutputInfo(att->atttypid,
2320 &foutoid, &typisvarlena);
2321 val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2322 }
2323
2324 if (write_comma)
2326 else
2327 write_comma = true;
2328
2329 /* truncate if needed */
2330 vallen = strlen(val);
2331 if (vallen <= maxfieldlen)
2332 appendBinaryStringInfo(&buf, val, vallen);
2333 else
2334 {
2335 vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2336 appendBinaryStringInfo(&buf, val, vallen);
2337 appendStringInfoString(&buf, "...");
2338 }
2339 }
2340 }
2341
2342 /* If we end up with zero columns being returned, then return NULL. */
2343 if (!any_perm)
2344 return NULL;
2345
2347
2348 if (!table_perm)
2349 {
2350 appendStringInfoString(&collist, ") = ");
2351 appendBinaryStringInfo(&collist, buf.data, buf.len);
2352
2353 return collist.data;
2354 }
2355
2356 return buf.data;
2357}
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:3836
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4007
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
#define NameStr(name)
Definition: c.h:703
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
long val
Definition: informix.c:689
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1083
Oid GetUserId(void)
Definition: miscinit.c:517
#define ACL_SELECT
Definition: parsenodes.h:77
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
static char * buf
Definition: pg_test_fsync.c:72
#define InvalidOid
Definition: postgres_ext.h:37
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
@ RLS_ENABLED
Definition: rls.h:45
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:153
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:368

References ACL_SELECT, ACLCHECK_OK, appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), bms_is_member(), buf, check_enable_rls(), StringInfoData::data, FirstLowInvalidHeapAttributeNumber, getTypeOutputInfo(), GetUserId(), i, initStringInfo(), InvalidOid, 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 build_tuple_value_details(), ExecConstraints(), ExecPartitionCheckEmitError(), and ExecWithCheckOptions().

◆ ExecCheckOneRelPerms()

static bool ExecCheckOneRelPerms ( RTEPermissionInfo perminfo)
static

Definition at line 643 of file execMain.c.

644{
645 AclMode requiredPerms;
646 AclMode relPerms;
647 AclMode remainingPerms;
648 Oid userid;
649 Oid relOid = perminfo->relid;
650
651 requiredPerms = perminfo->requiredPerms;
652 Assert(requiredPerms != 0);
653
654 /*
655 * userid to check as: current user unless we have a setuid indication.
656 *
657 * Note: GetUserId() is presently fast enough that there's no harm in
658 * calling it separately for each relation. If that stops being true, we
659 * could call it once in ExecCheckPermissions and pass the userid down
660 * from there. But for now, no need for the extra clutter.
661 */
662 userid = OidIsValid(perminfo->checkAsUser) ?
663 perminfo->checkAsUser : GetUserId();
664
665 /*
666 * We must have *all* the requiredPerms bits, but some of the bits can be
667 * satisfied from column-level rather than relation-level permissions.
668 * First, remove any bits that are satisfied by relation permissions.
669 */
670 relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL);
671 remainingPerms = requiredPerms & ~relPerms;
672 if (remainingPerms != 0)
673 {
674 int col = -1;
675
676 /*
677 * If we lack any permissions that exist only as relation permissions,
678 * we can fail straight away.
679 */
680 if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE))
681 return false;
682
683 /*
684 * Check to see if we have the needed privileges at column level.
685 *
686 * Note: failures just report a table-level error; it would be nicer
687 * to report a column-level error if we have some but not all of the
688 * column privileges.
689 */
690 if (remainingPerms & ACL_SELECT)
691 {
692 /*
693 * When the query doesn't explicitly reference any columns (for
694 * example, SELECT COUNT(*) FROM table), allow the query if we
695 * have SELECT on any column of the rel, as per SQL spec.
696 */
697 if (bms_is_empty(perminfo->selectedCols))
698 {
699 if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
701 return false;
702 }
703
704 while ((col = bms_next_member(perminfo->selectedCols, col)) >= 0)
705 {
706 /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
708
709 if (attno == InvalidAttrNumber)
710 {
711 /* Whole-row reference, must have priv on all cols */
712 if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
714 return false;
715 }
716 else
717 {
718 if (pg_attribute_aclcheck(relOid, attno, userid,
720 return false;
721 }
722 }
723 }
724
725 /*
726 * Basically the same for the mod columns, for both INSERT and UPDATE
727 * privilege as specified by remainingPerms.
728 */
729 if (remainingPerms & ACL_INSERT &&
731 userid,
732 perminfo->insertedCols,
733 ACL_INSERT))
734 return false;
735
736 if (remainingPerms & ACL_UPDATE &&
738 userid,
739 perminfo->updatedCols,
740 ACL_UPDATE))
741 return false;
742 }
743 return true;
744}
@ ACLMASK_ANY
Definition: acl.h:177
@ ACLMASK_ALL
Definition: acl.h:176
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:3878
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3240
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
#define bms_is_empty(a)
Definition: bitmapset.h:118
static bool ExecCheckPermissionsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms)
Definition: execMain.c:752
uint64 AclMode
Definition: parsenodes.h:74
#define ACL_INSERT
Definition: parsenodes.h:76
#define ACL_UPDATE
Definition: parsenodes.h:78
Bitmapset * selectedCols
Definition: parsenodes.h:1302
AclMode requiredPerms
Definition: parsenodes.h:1300
Bitmapset * insertedCols
Definition: parsenodes.h:1303
Bitmapset * updatedCols
Definition: parsenodes.h:1304

References ACL_INSERT, ACL_SELECT, ACL_UPDATE, ACLCHECK_OK, ACLMASK_ALL, ACLMASK_ANY, Assert, bms_is_empty, bms_next_member(), RTEPermissionInfo::checkAsUser, ExecCheckPermissionsModified(), FirstLowInvalidHeapAttributeNumber, GetUserId(), RTEPermissionInfo::insertedCols, InvalidAttrNumber, OidIsValid, pg_attribute_aclcheck(), pg_attribute_aclcheck_all(), pg_class_aclmask(), RTEPermissionInfo::relid, RTEPermissionInfo::requiredPerms, RTEPermissionInfo::selectedCols, and RTEPermissionInfo::updatedCols.

Referenced by ExecCheckPermissions().

◆ ExecCheckPermissions()

bool ExecCheckPermissions ( List rangeTable,
List rteperminfos,
bool  ereport_on_violation 
)

Definition at line 579 of file execMain.c.

581{
582 ListCell *l;
583 bool result = true;
584
585#ifdef USE_ASSERT_CHECKING
586 Bitmapset *indexset = NULL;
587
588 /* Check that rteperminfos is consistent with rangeTable */
589 foreach(l, rangeTable)
590 {
592
593 if (rte->perminfoindex != 0)
594 {
595 /* Sanity checks */
596
597 /*
598 * Only relation RTEs and subquery RTEs that were once relation
599 * RTEs (views) have their perminfoindex set.
600 */
601 Assert(rte->rtekind == RTE_RELATION ||
602 (rte->rtekind == RTE_SUBQUERY &&
603 rte->relkind == RELKIND_VIEW));
604
605 (void) getRTEPermissionInfo(rteperminfos, rte);
606 /* Many-to-one mapping not allowed */
607 Assert(!bms_is_member(rte->perminfoindex, indexset));
608 indexset = bms_add_member(indexset, rte->perminfoindex);
609 }
610 }
611
612 /* All rteperminfos are referenced */
613 Assert(bms_num_members(indexset) == list_length(rteperminfos));
614#endif
615
616 foreach(l, rteperminfos)
617 {
619
620 Assert(OidIsValid(perminfo->relid));
621 result = ExecCheckOneRelPerms(perminfo);
622 if (!result)
623 {
624 if (ereport_on_violation)
627 get_rel_name(perminfo->relid));
628 return false;
629 }
630 }
631
633 result = (*ExecutorCheckPerms_hook) (rangeTable, rteperminfos,
634 ereport_on_violation);
635 return result;
636}
@ ACLCHECK_NO_PRIV
Definition: acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2622
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:751
static bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
Definition: execMain.c:643
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:73
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2003
ObjectType get_relkind_objtype(char relkind)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_SUBQUERY
Definition: parsenodes.h:1027
@ RTE_RELATION
Definition: parsenodes.h:1026
#define lfirst_node(type, lc)
Definition: pg_list.h:176
RTEKind rtekind
Definition: parsenodes.h:1056

References aclcheck_error(), ACLCHECK_NO_PRIV, Assert, bms_add_member(), bms_is_member(), bms_num_members(), ExecCheckOneRelPerms(), ExecutorCheckPerms_hook, get_rel_name(), get_rel_relkind(), get_relkind_objtype(), getRTEPermissionInfo(), lfirst_node, list_length(), OidIsValid, RTEPermissionInfo::relid, RTE_RELATION, RTE_SUBQUERY, and RangeTblEntry::rtekind.

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

◆ ExecCheckPermissionsModified()

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

Definition at line 752 of file execMain.c.

754{
755 int col = -1;
756
757 /*
758 * When the query doesn't explicitly update any columns, allow the query
759 * if we have permission on any column of the rel. This is to handle
760 * SELECT FOR UPDATE as well as possible corner cases in UPDATE.
761 */
762 if (bms_is_empty(modifiedCols))
763 {
764 if (pg_attribute_aclcheck_all(relOid, userid, requiredPerms,
766 return false;
767 }
768
769 while ((col = bms_next_member(modifiedCols, col)) >= 0)
770 {
771 /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
773
774 if (attno == InvalidAttrNumber)
775 {
776 /* whole-row reference can't happen here */
777 elog(ERROR, "whole-row update is not implemented");
778 }
779 else
780 {
781 if (pg_attribute_aclcheck(relOid, attno, userid,
782 requiredPerms) != ACLCHECK_OK)
783 return false;
784 }
785 }
786 return true;
787}

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 ExecCheckOneRelPerms().

◆ ExecCheckXactReadOnly()

static void ExecCheckXactReadOnly ( PlannedStmt plannedstmt)
static

Definition at line 799 of file execMain.c.

800{
801 ListCell *l;
802
803 /*
804 * Fail if write permissions are requested in parallel mode for table
805 * (temp or non-temp), otherwise fail for any non-temp table.
806 */
807 foreach(l, plannedstmt->permInfos)
808 {
810
811 if ((perminfo->requiredPerms & (~ACL_SELECT)) == 0)
812 continue;
813
815 continue;
816
818 }
819
820 if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
822}
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1952
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3649
@ CMD_SELECT
Definition: nodes.h:265
Definition: nodes.h:129
bool hasModifyingCTE
Definition: plannodes.h:58
List * permInfos
Definition: plannodes.h:74
CmdType commandType
Definition: plannodes.h:52
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:404
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:422
static const char * CreateCommandName(Node *parsetree)
Definition: utility.h:103

References ACL_SELECT, CMD_SELECT, PlannedStmt::commandType, CreateCommandName(), get_rel_namespace(), PlannedStmt::hasModifyingCTE, isTempNamespace(), lfirst_node, PlannedStmt::permInfos, PreventCommandIfParallelMode(), PreventCommandIfReadOnly(), RTEPermissionInfo::relid, and RTEPermissionInfo::requiredPerms.

Referenced by standard_ExecutorStart().

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1584 of file execMain.c.

1585{
1586 int i;
1587
1588 for (i = 0; i < estate->es_range_table_size; i++)
1589 {
1590 if (estate->es_relations[i])
1591 table_close(estate->es_relations[i], NoLock);
1592 }
1593}
#define NoLock
Definition: lockdefs.h:34
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126

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

Referenced by CopyFrom(), and ExecEndPlan().

◆ ExecCloseResultRelations()

void ExecCloseResultRelations ( EState estate)

Definition at line 1524 of file execMain.c.

1525{
1526 ListCell *l;
1527
1528 /*
1529 * close indexes of result relation(s) if any. (Rels themselves are
1530 * closed in ExecCloseRangeTableRelations())
1531 *
1532 * In addition, close the stub RTs that may be in each resultrel's
1533 * ri_ancestorResultRels.
1534 */
1535 foreach(l, estate->es_opened_result_relations)
1536 {
1537 ResultRelInfo *resultRelInfo = lfirst(l);
1538 ListCell *lc;
1539
1540 ExecCloseIndices(resultRelInfo);
1541 foreach(lc, resultRelInfo->ri_ancestorResultRels)
1542 {
1543 ResultRelInfo *rInfo = lfirst(lc);
1544
1545 /*
1546 * Ancestors with RTI > 0 (should only be the root ancestor) are
1547 * closed by ExecCloseRangeTableRelations.
1548 */
1549 if (rInfo->ri_RangeTableIndex > 0)
1550 continue;
1551
1553 }
1554 }
1555
1556 /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
1557 foreach(l, estate->es_trig_target_relations)
1558 {
1559 ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1560
1561 /*
1562 * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
1563 * might be issuing a duplicate close against a Relation opened by
1564 * ExecGetRangeTableRelation.
1565 */
1566 Assert(resultRelInfo->ri_RangeTableIndex == 0);
1567
1568 /*
1569 * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
1570 * these rels, we needn't call ExecCloseIndices either.
1571 */
1572 Assert(resultRelInfo->ri_NumIndices == 0);
1573
1574 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1575 }
1576}
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:236
List * es_trig_target_relations
Definition: execnodes.h:682
List * es_opened_result_relations
Definition: execnodes.h:669
int ri_NumIndices
Definition: execnodes.h:477
Index ri_RangeTableIndex
Definition: execnodes.h:471
List * ri_ancestorResultRels
Definition: execnodes.h:616

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

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

◆ ExecConstraints()

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

Definition at line 1930 of file execMain.c.

1932{
1933 Relation rel = resultRelInfo->ri_RelationDesc;
1934 TupleDesc tupdesc = RelationGetDescr(rel);
1935 TupleConstr *constr = tupdesc->constr;
1936 Bitmapset *modifiedCols;
1937
1938 Assert(constr); /* we should not be called otherwise */
1939
1940 if (constr->has_not_null)
1941 {
1942 int natts = tupdesc->natts;
1943 int attrChk;
1944
1945 for (attrChk = 1; attrChk <= natts; attrChk++)
1946 {
1947 Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
1948
1949 if (att->attnotnull && slot_attisnull(slot, attrChk))
1950 {
1951 char *val_desc;
1952 Relation orig_rel = rel;
1953 TupleDesc orig_tupdesc = RelationGetDescr(rel);
1954
1955 /*
1956 * If the tuple has been routed, it's been converted to the
1957 * partition's rowtype, which might differ from the root
1958 * table's. We must convert it back to the root table's
1959 * rowtype so that val_desc shown error message matches the
1960 * input tuple.
1961 */
1962 if (resultRelInfo->ri_RootResultRelInfo)
1963 {
1964 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1965 AttrMap *map;
1966
1967 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1968 /* a reverse map */
1969 map = build_attrmap_by_name_if_req(orig_tupdesc,
1970 tupdesc,
1971 false);
1972
1973 /*
1974 * Partition-specific slot's tupdesc can't be changed, so
1975 * allocate a new one.
1976 */
1977 if (map != NULL)
1978 slot = execute_attr_map_slot(map, slot,
1980 modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
1981 ExecGetUpdatedCols(rootrel, estate));
1982 rel = rootrel->ri_RelationDesc;
1983 }
1984 else
1985 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1986 ExecGetUpdatedCols(resultRelInfo, estate));
1988 slot,
1989 tupdesc,
1990 modifiedCols,
1991 64);
1992
1993 ereport(ERROR,
1994 (errcode(ERRCODE_NOT_NULL_VIOLATION),
1995 errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
1996 NameStr(att->attname),
1997 RelationGetRelationName(orig_rel)),
1998 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1999 errtablecol(orig_rel, attrChk)));
2000 }
2001 }
2002 }
2003
2004 if (rel->rd_rel->relchecks > 0)
2005 {
2006 const char *failed;
2007
2008 if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2009 {
2010 char *val_desc;
2011 Relation orig_rel = rel;
2012
2013 /* See the comment above. */
2014 if (resultRelInfo->ri_RootResultRelInfo)
2015 {
2016 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2017 TupleDesc old_tupdesc = RelationGetDescr(rel);
2018 AttrMap *map;
2019
2020 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2021 /* a reverse map */
2022 map = build_attrmap_by_name_if_req(old_tupdesc,
2023 tupdesc,
2024 false);
2025
2026 /*
2027 * Partition-specific slot's tupdesc can't be changed, so
2028 * allocate a new one.
2029 */
2030 if (map != NULL)
2031 slot = execute_attr_map_slot(map, slot,
2033 modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
2034 ExecGetUpdatedCols(rootrel, estate));
2035 rel = rootrel->ri_RelationDesc;
2036 }
2037 else
2038 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2039 ExecGetUpdatedCols(resultRelInfo, estate));
2041 slot,
2042 tupdesc,
2043 modifiedCols,
2044 64);
2045 ereport(ERROR,
2046 (errcode(ERRCODE_CHECK_VIOLATION),
2047 errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2048 RelationGetRelationName(orig_rel), failed),
2049 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2050 errtableconstraint(orig_rel, failed)));
2051 }
2052 }
2053}
AttrMap * build_attrmap_by_name_if_req(TupleDesc indesc, TupleDesc outdesc, bool missing_ok)
Definition: attmap.c:263
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:251
int errdetail(const char *fmt,...)
Definition: elog.c:1203
char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2228
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1727
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1299
Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1340
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1361
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:6023
int errtablecol(Relation rel, int attnum)
Definition: relcache.c:5986
Definition: attmap.h:35
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:606
bool has_not_null
Definition: tupdesc.h:45
TupleConstr * constr
Definition: tupdesc.h:134
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:192
static bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: tuptable.h:381

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(), NameStr, TupleDescData::natts, RelationData::rd_rel, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, slot_attisnull(), TTSOpsVirtual, and TupleDescAttr().

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

◆ ExecEndPlan()

static void ExecEndPlan ( PlanState planstate,
EState estate 
)
static

Definition at line 1485 of file execMain.c.

1486{
1487 ListCell *l;
1488
1489 /*
1490 * shut down the node-type-specific query processing
1491 */
1492 ExecEndNode(planstate);
1493
1494 /*
1495 * for subplans too
1496 */
1497 foreach(l, estate->es_subplanstates)
1498 {
1499 PlanState *subplanstate = (PlanState *) lfirst(l);
1500
1501 ExecEndNode(subplanstate);
1502 }
1503
1504 /*
1505 * destroy the executor's tuple table. Actually we only care about
1506 * releasing buffer pins and tupdesc refcounts; there's no need to pfree
1507 * the TupleTableSlots, since the containing memory context is about to go
1508 * away anyway.
1509 */
1510 ExecResetTupleTable(estate->es_tupleTable, false);
1511
1512 /*
1513 * Close any Relations that have been opened for range table entries or
1514 * result relations.
1515 */
1518}
void ExecCloseRangeTableRelations(EState *estate)
Definition: execMain.c:1584

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

Referenced by standard_ExecutorEnd().

◆ ExecFindRowMark()

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

Definition at line 2391 of file execMain.c.

2392{
2393 if (rti > 0 && rti <= estate->es_range_table_size &&
2394 estate->es_rowmarks != NULL)
2395 {
2396 ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2397
2398 if (erm)
2399 return erm;
2400 }
2401 if (!missing_ok)
2402 elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2403 return NULL;
2404}

References elog, ERROR, and EState::es_rowmarks.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecGetAncestorResultRels()

List * ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1379 of file execMain.c.

1380{
1381 ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1382 Relation partRel = resultRelInfo->ri_RelationDesc;
1383 Oid rootRelOid;
1384
1385 if (!partRel->rd_rel->relispartition)
1386 elog(ERROR, "cannot find ancestors of a non-partition result relation");
1387 Assert(rootRelInfo != NULL);
1388 rootRelOid = RelationGetRelid(rootRelInfo->ri_RelationDesc);
1389 if (resultRelInfo->ri_ancestorResultRels == NIL)
1390 {
1391 ListCell *lc;
1393 List *ancResultRels = NIL;
1394
1395 foreach(lc, oids)
1396 {
1397 Oid ancOid = lfirst_oid(lc);
1398 Relation ancRel;
1399 ResultRelInfo *rInfo;
1400
1401 /*
1402 * Ignore the root ancestor here, and use ri_RootResultRelInfo
1403 * (below) for it instead. Also, we stop climbing up the
1404 * hierarchy when we find the table that was mentioned in the
1405 * query.
1406 */
1407 if (ancOid == rootRelOid)
1408 break;
1409
1410 /*
1411 * All ancestors up to the root target relation must have been
1412 * locked by the planner or AcquireExecutorLocks().
1413 */
1414 ancRel = table_open(ancOid, NoLock);
1415 rInfo = makeNode(ResultRelInfo);
1416
1417 /* dummy rangetable index */
1418 InitResultRelInfo(rInfo, ancRel, 0, NULL,
1419 estate->es_instrument);
1420 ancResultRels = lappend(ancResultRels, rInfo);
1421 }
1422 ancResultRels = lappend(ancResultRels, rootRelInfo);
1423 resultRelInfo->ri_ancestorResultRels = ancResultRels;
1424 }
1425
1426 /* We must have found some ancestor */
1427 Assert(resultRelInfo->ri_ancestorResultRels != NIL);
1428
1429 return resultRelInfo->ri_ancestorResultRels;
1430}
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
Definition: execMain.c:1203
#define makeNode(_type_)
Definition: nodes.h:155
List * get_partition_ancestors(Oid relid)
Definition: partition.c:134
#define lfirst_oid(lc)
Definition: pg_list.h:174
Definition: pg_list.h:54
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References Assert, elog, ERROR, EState::es_instrument, get_partition_ancestors(), InitResultRelInfo(), lappend(), lfirst_oid, makeNode, NIL, NoLock, RelationData::rd_rel, RelationGetRelid, ResultRelInfo::ri_ancestorResultRels, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, and table_open().

Referenced by ExecCrossPartitionUpdateForeignKey().

◆ ExecGetTriggerResultRel()

ResultRelInfo * ExecGetTriggerResultRel ( EState estate,
Oid  relid,
ResultRelInfo rootRelInfo 
)

Definition at line 1303 of file execMain.c.

1305{
1306 ResultRelInfo *rInfo;
1307 ListCell *l;
1308 Relation rel;
1309 MemoryContext oldcontext;
1310
1311 /* Search through the query result relations */
1312 foreach(l, estate->es_opened_result_relations)
1313 {
1314 rInfo = lfirst(l);
1315 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1316 return rInfo;
1317 }
1318
1319 /*
1320 * Search through the result relations that were created during tuple
1321 * routing, if any.
1322 */
1323 foreach(l, estate->es_tuple_routing_result_relations)
1324 {
1325 rInfo = (ResultRelInfo *) lfirst(l);
1326 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1327 return rInfo;
1328 }
1329
1330 /* Nope, but maybe we already made an extra ResultRelInfo for it */
1331 foreach(l, estate->es_trig_target_relations)
1332 {
1333 rInfo = (ResultRelInfo *) lfirst(l);
1334 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1335 return rInfo;
1336 }
1337 /* Nope, so we need a new one */
1338
1339 /*
1340 * Open the target relation's relcache entry. We assume that an
1341 * appropriate lock is still held by the backend from whenever the trigger
1342 * event got queued, so we need take no new lock here. Also, we need not
1343 * recheck the relkind, so no need for CheckValidResultRel.
1344 */
1345 rel = table_open(relid, NoLock);
1346
1347 /*
1348 * Make the new entry in the right context.
1349 */
1350 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1351 rInfo = makeNode(ResultRelInfo);
1352 InitResultRelInfo(rInfo,
1353 rel,
1354 0, /* dummy rangetable index */
1355 rootRelInfo,
1356 estate->es_instrument);
1357 estate->es_trig_target_relations =
1358 lappend(estate->es_trig_target_relations, rInfo);
1359 MemoryContextSwitchTo(oldcontext);
1360
1361 /*
1362 * Currently, we don't need any index information in ResultRelInfos used
1363 * only for triggers, so no need to call ExecOpenIndices.
1364 */
1365
1366 return rInfo;
1367}
List * es_tuple_routing_result_relations
Definition: execnodes.h:679

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

◆ ExecPartitionCheck()

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

Definition at line 1806 of file execMain.c.

1808{
1809 ExprContext *econtext;
1810 bool success;
1811
1812 /*
1813 * If first time through, build expression state tree for the partition
1814 * check expression. (In the corner case where the partition check
1815 * expression is empty, ie there's a default partition and nothing else,
1816 * we'll be fooled into executing this code each time through. But it's
1817 * pretty darn cheap in that case, so we don't worry about it.)
1818 */
1819 if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1820 {
1821 /*
1822 * Ensure that the qual tree and prepared expression are in the
1823 * query-lifespan context.
1824 */
1826 List *qual = RelationGetPartitionQual(resultRelInfo->ri_RelationDesc);
1827
1828 resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1829 MemoryContextSwitchTo(oldcxt);
1830 }
1831
1832 /*
1833 * We will use the EState's per-tuple context for evaluating constraint
1834 * expressions (creating it if it's not already there).
1835 */
1836 econtext = GetPerTupleExprContext(estate);
1837
1838 /* Arrange for econtext's scan tuple to be the tuple under test */
1839 econtext->ecxt_scantuple = slot;
1840
1841 /*
1842 * As in case of the cataloged constraints, we treat a NULL result as
1843 * success here, not a failure.
1844 */
1845 success = ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
1846
1847 /* if asked to emit error, don't actually return on failure */
1848 if (!success && emitError)
1849 ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
1850
1851 return success;
1852}
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:872
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:816
void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1859
static bool success
Definition: initdb.c:186
List * RelationGetPartitionQual(Relation rel)
Definition: partcache.c:277
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:267
ExprState * ri_PartitionCheckExpr
Definition: execnodes.h:578

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(), ExecInsert(), ExecSimpleRelationInsert(), ExecSimpleRelationUpdate(), and ExecUpdateAct().

◆ ExecPartitionCheckEmitError()

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

Definition at line 1859 of file execMain.c.

1862{
1863 Oid root_relid;
1864 TupleDesc tupdesc;
1865 char *val_desc;
1866 Bitmapset *modifiedCols;
1867
1868 /*
1869 * If the tuple has been routed, it's been converted to the partition's
1870 * rowtype, which might differ from the root table's. We must convert it
1871 * back to the root table's rowtype so that val_desc in the error message
1872 * matches the input tuple.
1873 */
1874 if (resultRelInfo->ri_RootResultRelInfo)
1875 {
1876 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1877 TupleDesc old_tupdesc;
1878 AttrMap *map;
1879
1880 root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
1881 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1882
1883 old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1884 /* a reverse map */
1885 map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc, false);
1886
1887 /*
1888 * Partition-specific slot's tupdesc can't be changed, so allocate a
1889 * new one.
1890 */
1891 if (map != NULL)
1892 slot = execute_attr_map_slot(map, slot,
1894 modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
1895 ExecGetUpdatedCols(rootrel, estate));
1896 }
1897 else
1898 {
1899 root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1900 tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1901 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1902 ExecGetUpdatedCols(resultRelInfo, estate));
1903 }
1904
1905 val_desc = ExecBuildSlotValueDescription(root_relid,
1906 slot,
1907 tupdesc,
1908 modifiedCols,
1909 64);
1910 ereport(ERROR,
1911 (errcode(ERRCODE_CHECK_VIOLATION),
1912 errmsg("new row for relation \"%s\" violates partition constraint",
1914 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1915 errtable(resultRelInfo->ri_RelationDesc)));
1916}
int errtable(Relation rel)
Definition: relcache.c:5969

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

Referenced by ExecCrossPartitionUpdate(), and ExecPartitionCheck().

◆ ExecPostprocessPlan()

static void ExecPostprocessPlan ( EState estate)
static

Definition at line 1439 of file execMain.c.

1440{
1441 ListCell *lc;
1442
1443 /*
1444 * Make sure nodes run forward.
1445 */
1447
1448 /*
1449 * Run any secondary ModifyTable nodes to completion, in case the main
1450 * query did not fetch all rows from them. (We do this to ensure that
1451 * such nodes have predictable results.)
1452 */
1453 foreach(lc, estate->es_auxmodifytables)
1454 {
1455 PlanState *ps = (PlanState *) lfirst(lc);
1456
1457 for (;;)
1458 {
1459 TupleTableSlot *slot;
1460
1461 /* Reset the per-output-tuple exprcontext each time */
1463
1464 slot = ExecProcNode(ps);
1465
1466 if (TupIsNull(slot))
1467 break;
1468 }
1469 }
1470}
#define ResetPerTupleExprContext(estate)
Definition: executor.h:572
struct parser_state ps
List * es_auxmodifytables
Definition: execnodes.h:708

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

Referenced by standard_ExecutorFinish().

◆ ExecRelCheck()

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

Definition at line 1727 of file execMain.c.

1729{
1730 Relation rel = resultRelInfo->ri_RelationDesc;
1731 int ncheck = rel->rd_att->constr->num_check;
1732 ConstrCheck *check = rel->rd_att->constr->check;
1733 ExprContext *econtext;
1734 MemoryContext oldContext;
1735 int i;
1736
1737 /*
1738 * CheckConstraintFetch let this pass with only a warning, but now we
1739 * should fail rather than possibly failing to enforce an important
1740 * constraint.
1741 */
1742 if (ncheck != rel->rd_rel->relchecks)
1743 elog(ERROR, "%d pg_constraint record(s) missing for relation \"%s\"",
1744 rel->rd_rel->relchecks - ncheck, RelationGetRelationName(rel));
1745
1746 /*
1747 * If first time through for this result relation, build expression
1748 * nodetrees for rel's constraint expressions. Keep them in the per-query
1749 * memory context so they'll survive throughout the query.
1750 */
1751 if (resultRelInfo->ri_ConstraintExprs == NULL)
1752 {
1753 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
1754 resultRelInfo->ri_ConstraintExprs =
1755 (ExprState **) palloc0(ncheck * sizeof(ExprState *));
1756 for (i = 0; i < ncheck; i++)
1757 {
1758 Expr *checkconstr;
1759
1760 /* Skip not enforced constraint */
1761 if (!check[i].ccenforced)
1762 continue;
1763
1764 checkconstr = stringToNode(check[i].ccbin);
1765 resultRelInfo->ri_ConstraintExprs[i] =
1766 ExecPrepareExpr(checkconstr, estate);
1767 }
1768 MemoryContextSwitchTo(oldContext);
1769 }
1770
1771 /*
1772 * We will use the EState's per-tuple context for evaluating constraint
1773 * expressions (creating it if it's not already there).
1774 */
1775 econtext = GetPerTupleExprContext(estate);
1776
1777 /* Arrange for econtext's scan tuple to be the tuple under test */
1778 econtext->ecxt_scantuple = slot;
1779
1780 /* And evaluate the constraints */
1781 for (i = 0; i < ncheck; i++)
1782 {
1783 ExprState *checkconstr = resultRelInfo->ri_ConstraintExprs[i];
1784
1785 /*
1786 * NOTE: SQL specifies that a NULL result from a constraint expression
1787 * is not to be treated as a failure. Therefore, use ExecCheck not
1788 * ExecQual.
1789 */
1790 if (checkconstr && !ExecCheck(checkconstr, econtext))
1791 return check[i].ccname;
1792 }
1793
1794 /* NULL result means no error */
1795 return NULL;
1796}
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:765
void * stringToNode(const char *str)
Definition: read.c:90
char * ccname
Definition: tupdesc.h:30
TupleDesc rd_att
Definition: rel.h:112
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:547
ConstrCheck * check
Definition: tupdesc.h:41
uint16 num_check
Definition: tupdesc.h:44

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

Referenced by ExecConstraints().

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2365 of file execMain.c.

2366{
2367 Bitmapset *keyCols;
2368 Bitmapset *updatedCols;
2369
2370 /*
2371 * Compute lock mode to use. If columns that are part of the key have not
2372 * been modified, then we can use a weaker lock, allowing for better
2373 * concurrency.
2374 */
2375 updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2378
2379 if (bms_overlap(keyCols, updatedCols))
2380 return LockTupleExclusive;
2381
2383}
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1397
@ LockTupleExclusive
Definition: lockoptions.h:58
@ LockTupleNoKeyExclusive
Definition: lockoptions.h:56
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:5223
@ INDEX_ATTR_BITMAP_KEY
Definition: relcache.h:61

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

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

◆ ExecutePlan()

static void ExecutePlan ( QueryDesc queryDesc,
CmdType  operation,
bool  sendTuples,
uint64  numberTuples,
ScanDirection  direction,
DestReceiver dest 
)
static

Definition at line 1605 of file execMain.c.

1611{
1612 EState *estate = queryDesc->estate;
1613 PlanState *planstate = queryDesc->planstate;
1614 bool use_parallel_mode;
1615 TupleTableSlot *slot;
1616 uint64 current_tuple_count;
1617
1618 /*
1619 * initialize local variables
1620 */
1621 current_tuple_count = 0;
1622
1623 /*
1624 * Set the direction.
1625 */
1626 estate->es_direction = direction;
1627
1628 /*
1629 * Set up parallel mode if appropriate.
1630 *
1631 * Parallel mode only supports complete execution of a plan. If we've
1632 * already partially executed it, or if the caller asks us to exit early,
1633 * we must force the plan to run without parallelism.
1634 */
1635 if (queryDesc->already_executed || numberTuples != 0)
1636 use_parallel_mode = false;
1637 else
1638 use_parallel_mode = queryDesc->plannedstmt->parallelModeNeeded;
1639 queryDesc->already_executed = true;
1640
1641 estate->es_use_parallel_mode = use_parallel_mode;
1642 if (use_parallel_mode)
1644
1645 /*
1646 * Loop until we've processed the proper number of tuples from the plan.
1647 */
1648 for (;;)
1649 {
1650 /* Reset the per-output-tuple exprcontext */
1652
1653 /*
1654 * Execute the plan and obtain a tuple
1655 */
1656 slot = ExecProcNode(planstate);
1657
1658 /*
1659 * if the tuple is null, then we assume there is nothing more to
1660 * process so we just end the loop...
1661 */
1662 if (TupIsNull(slot))
1663 break;
1664
1665 /*
1666 * If we have a junk filter, then project a new tuple with the junk
1667 * removed.
1668 *
1669 * Store this new "clean" tuple in the junkfilter's resultSlot.
1670 * (Formerly, we stored it back over the "dirty" tuple, which is WRONG
1671 * because that tuple slot has the wrong descriptor.)
1672 */
1673 if (estate->es_junkFilter != NULL)
1674 slot = ExecFilterJunk(estate->es_junkFilter, slot);
1675
1676 /*
1677 * If we are supposed to send the tuple somewhere, do so. (In
1678 * practice, this is probably always the case at this point.)
1679 */
1680 if (sendTuples)
1681 {
1682 /*
1683 * If we are not able to send the tuple, we assume the destination
1684 * has closed and no more tuples can be sent. If that's the case,
1685 * end the loop.
1686 */
1687 if (!dest->receiveSlot(slot, dest))
1688 break;
1689 }
1690
1691 /*
1692 * Count tuples processed, if this is a SELECT. (For other operation
1693 * types, the ModifyTable plan node must count the appropriate
1694 * events.)
1695 */
1696 if (operation == CMD_SELECT)
1697 (estate->es_processed)++;
1698
1699 /*
1700 * check our tuple count.. if we've processed the proper number then
1701 * quit, else loop again and process more tuples. Zero numberTuples
1702 * means no limit.
1703 */
1704 current_tuple_count++;
1705 if (numberTuples && numberTuples == current_tuple_count)
1706 break;
1707 }
1708
1709 /*
1710 * If we know we won't need to back up, we can release resources at this
1711 * point.
1712 */
1713 if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))
1714 ExecShutdownNode(planstate);
1715
1716 if (use_parallel_mode)
1718}
uint64_t uint64
Definition: c.h:489
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:247
void ExecShutdownNode(PlanState *node)
Definition: execProcnode.c:772
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
uint64 es_processed
Definition: execnodes.h:695
bool es_use_parallel_mode
Definition: execnodes.h:725
bool parallelModeNeeded
Definition: plannodes.h:66
EState * estate
Definition: execdesc.h:48
bool already_executed
Definition: execdesc.h:52
PlannedStmt * plannedstmt
Definition: execdesc.h:37
PlanState * planstate
Definition: execdesc.h:49
void ExitParallelMode(void)
Definition: xact.c:1063
void EnterParallelMode(void)
Definition: xact.c:1050

References QueryDesc::already_executed, CMD_SELECT, generate_unaccent_rules::dest, EnterParallelMode(), EState::es_direction, EState::es_junkFilter, EState::es_processed, EState::es_top_eflags, EState::es_use_parallel_mode, QueryDesc::estate, EXEC_FLAG_BACKWARD, ExecFilterJunk(), ExecProcNode(), ExecShutdownNode(), ExitParallelMode(), PlannedStmt::parallelModeNeeded, QueryDesc::plannedstmt, QueryDesc::planstate, ResetPerTupleExprContext, and TupIsNull.

Referenced by standard_ExecutorRun().

◆ ExecutorEnd()

void ExecutorEnd ( QueryDesc queryDesc)

Definition at line 463 of file execMain.c.

464{
466 (*ExecutorEnd_hook) (queryDesc);
467 else
468 standard_ExecutorEnd(queryDesc);
469}
ExecutorEnd_hook_type ExecutorEnd_hook
Definition: execMain.c:70
void standard_ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:472

References ExecutorEnd_hook, and standard_ExecutorEnd().

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

◆ ExecutorFinish()

void ExecutorFinish ( QueryDesc queryDesc)

Definition at line 403 of file execMain.c.

404{
406 (*ExecutorFinish_hook) (queryDesc);
407 else
408 standard_ExecutorFinish(queryDesc);
409}
ExecutorFinish_hook_type ExecutorFinish_hook
Definition: execMain.c:69
void standard_ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:412

References ExecutorFinish_hook, and standard_ExecutorFinish().

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

◆ ExecutorRewind()

void ExecutorRewind ( QueryDesc queryDesc)

Definition at line 533 of file execMain.c.

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

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

Referenced by DoPortalRewind(), and PersistHoldablePortal().

◆ ExecutorRun()

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

Definition at line 294 of file execMain.c.

296{
298 (*ExecutorRun_hook) (queryDesc, direction, count);
299 else
300 standard_ExecutorRun(queryDesc, direction, count);
301}
ExecutorRun_hook_type ExecutorRun_hook
Definition: execMain.c:68
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:304

References ExecutorRun_hook, and standard_ExecutorRun().

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

◆ ExecutorStart()

void ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 119 of file execMain.c.

120{
121 /*
122 * In some cases (e.g. an EXECUTE statement or an execute message with the
123 * extended query protocol) the query_id won't be reported, so do it now.
124 *
125 * Note that it's harmless to report the query_id multiple times, as the
126 * call will be ignored if the top level query_id has already been
127 * reported.
128 */
129 pgstat_report_query_id(queryDesc->plannedstmt->queryId, false);
130
132 (*ExecutorStart_hook) (queryDesc, eflags);
133 else
134 standard_ExecutorStart(queryDesc, eflags);
135}
void pgstat_report_query_id(uint64 query_id, bool force)
ExecutorStart_hook_type ExecutorStart_hook
Definition: execMain.c:67
void standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:138
uint64 queryId
Definition: plannodes.h:54

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

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

◆ ExecWithCheckOptions()

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

Definition at line 2065 of file execMain.c.

2067{
2068 Relation rel = resultRelInfo->ri_RelationDesc;
2069 TupleDesc tupdesc = RelationGetDescr(rel);
2070 ExprContext *econtext;
2071 ListCell *l1,
2072 *l2;
2073
2074 /*
2075 * We will use the EState's per-tuple context for evaluating constraint
2076 * expressions (creating it if it's not already there).
2077 */
2078 econtext = GetPerTupleExprContext(estate);
2079
2080 /* Arrange for econtext's scan tuple to be the tuple under test */
2081 econtext->ecxt_scantuple = slot;
2082
2083 /* Check each of the constraints */
2084 forboth(l1, resultRelInfo->ri_WithCheckOptions,
2085 l2, resultRelInfo->ri_WithCheckOptionExprs)
2086 {
2087 WithCheckOption *wco = (WithCheckOption *) lfirst(l1);
2088 ExprState *wcoExpr = (ExprState *) lfirst(l2);
2089
2090 /*
2091 * Skip any WCOs which are not the kind we are looking for at this
2092 * time.
2093 */
2094 if (wco->kind != kind)
2095 continue;
2096
2097 /*
2098 * WITH CHECK OPTION checks are intended to ensure that the new tuple
2099 * is visible (in the case of a view) or that it passes the
2100 * 'with-check' policy (in the case of row security). If the qual
2101 * evaluates to NULL or FALSE, then the new tuple won't be included in
2102 * the view or doesn't pass the 'with-check' policy for the table.
2103 */
2104 if (!ExecQual(wcoExpr, econtext))
2105 {
2106 char *val_desc;
2107 Bitmapset *modifiedCols;
2108
2109 switch (wco->kind)
2110 {
2111 /*
2112 * For WITH CHECK OPTIONs coming from views, we might be
2113 * able to provide the details on the row, depending on
2114 * the permissions on the relation (that is, if the user
2115 * could view it directly anyway). For RLS violations, we
2116 * don't include the data since we don't know if the user
2117 * should be able to view the tuple as that depends on the
2118 * USING policy.
2119 */
2120 case WCO_VIEW_CHECK:
2121 /* See the comment in ExecConstraints(). */
2122 if (resultRelInfo->ri_RootResultRelInfo)
2123 {
2124 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2125 TupleDesc old_tupdesc = RelationGetDescr(rel);
2126 AttrMap *map;
2127
2128 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2129 /* a reverse map */
2130 map = build_attrmap_by_name_if_req(old_tupdesc,
2131 tupdesc,
2132 false);
2133
2134 /*
2135 * Partition-specific slot's tupdesc can't be changed,
2136 * so allocate a new one.
2137 */
2138 if (map != NULL)
2139 slot = execute_attr_map_slot(map, slot,
2141
2142 modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
2143 ExecGetUpdatedCols(rootrel, estate));
2144 rel = rootrel->ri_RelationDesc;
2145 }
2146 else
2147 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2148 ExecGetUpdatedCols(resultRelInfo, estate));
2150 slot,
2151 tupdesc,
2152 modifiedCols,
2153 64);
2154
2155 ereport(ERROR,
2156 (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),
2157 errmsg("new row violates check option for view \"%s\"",
2158 wco->relname),
2159 val_desc ? errdetail("Failing row contains %s.",
2160 val_desc) : 0));
2161 break;
2164 if (wco->polname != NULL)
2165 ereport(ERROR,
2166 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2167 errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
2168 wco->polname, wco->relname)));
2169 else
2170 ereport(ERROR,
2171 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2172 errmsg("new row violates row-level security policy for table \"%s\"",
2173 wco->relname)));
2174 break;
2177 if (wco->polname != NULL)
2178 ereport(ERROR,
2179 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2180 errmsg("target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2181 wco->polname, wco->relname)));
2182 else
2183 ereport(ERROR,
2184 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2185 errmsg("target row violates row-level security policy (USING expression) for table \"%s\"",
2186 wco->relname)));
2187 break;
2189 if (wco->polname != NULL)
2190 ereport(ERROR,
2191 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2192 errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2193 wco->polname, wco->relname)));
2194 else
2195 ereport(ERROR,
2196 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2197 errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
2198 wco->relname)));
2199 break;
2200 default:
2201 elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
2202 break;
2203 }
2204 }
2205 }
2206}
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:426
@ WCO_RLS_MERGE_UPDATE_CHECK
Definition: parsenodes.h:1372
@ WCO_RLS_CONFLICT_CHECK
Definition: parsenodes.h:1371
@ WCO_RLS_INSERT_CHECK
Definition: parsenodes.h:1369
@ WCO_VIEW_CHECK
Definition: parsenodes.h:1368
@ WCO_RLS_UPDATE_CHECK
Definition: parsenodes.h:1370
@ WCO_RLS_MERGE_DELETE_CHECK
Definition: parsenodes.h:1373
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
List * ri_WithCheckOptions
Definition: execnodes.h:541
List * ri_WithCheckOptionExprs
Definition: execnodes.h:544

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(), WithCheckOption::polname, RelationGetDescr, RelationGetRelid, WithCheckOption::relname, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, ResultRelInfo::ri_WithCheckOptionExprs, ResultRelInfo::ri_WithCheckOptions, TTSOpsVirtual, WCO_RLS_CONFLICT_CHECK, WCO_RLS_INSERT_CHECK, WCO_RLS_MERGE_DELETE_CHECK, WCO_RLS_MERGE_UPDATE_CHECK, WCO_RLS_UPDATE_CHECK, and WCO_VIEW_CHECK.

Referenced by ExecBatchInsert(), ExecInsert(), ExecMergeMatched(), ExecOnConflictUpdate(), ExecUpdateAct(), and ExecUpdateEpilogue().

◆ InitPlan()

static void InitPlan ( QueryDesc queryDesc,
int  eflags 
)
static

Definition at line 833 of file execMain.c.

834{
835 CmdType operation = queryDesc->operation;
836 PlannedStmt *plannedstmt = queryDesc->plannedstmt;
837 Plan *plan = plannedstmt->planTree;
838 List *rangeTable = plannedstmt->rtable;
839 EState *estate = queryDesc->estate;
840 PlanState *planstate;
841 TupleDesc tupType;
842 ListCell *l;
843 int i;
844
845 /*
846 * Do permissions checks
847 */
848 ExecCheckPermissions(rangeTable, plannedstmt->permInfos, true);
849
850 /*
851 * initialize the node's execution state
852 */
853 ExecInitRangeTable(estate, rangeTable, plannedstmt->permInfos);
854
855 estate->es_plannedstmt = plannedstmt;
856
857 /*
858 * Next, build the ExecRowMark array from the PlanRowMark(s), if any.
859 */
860 if (plannedstmt->rowMarks)
861 {
862 estate->es_rowmarks = (ExecRowMark **)
863 palloc0(estate->es_range_table_size * sizeof(ExecRowMark *));
864 foreach(l, plannedstmt->rowMarks)
865 {
866 PlanRowMark *rc = (PlanRowMark *) lfirst(l);
867 Oid relid;
868 Relation relation;
869 ExecRowMark *erm;
870
871 /* ignore "parent" rowmarks; they are irrelevant at runtime */
872 if (rc->isParent)
873 continue;
874
875 /* get relation's OID (will produce InvalidOid if subquery) */
876 relid = exec_rt_fetch(rc->rti, estate)->relid;
877
878 /* open relation, if we need to access it for this mark type */
879 switch (rc->markType)
880 {
883 case ROW_MARK_SHARE:
886 relation = ExecGetRangeTableRelation(estate, rc->rti);
887 break;
888 case ROW_MARK_COPY:
889 /* no physical table access is required */
890 relation = NULL;
891 break;
892 default:
893 elog(ERROR, "unrecognized markType: %d", rc->markType);
894 relation = NULL; /* keep compiler quiet */
895 break;
896 }
897
898 /* Check that relation is a legal target for marking */
899 if (relation)
900 CheckValidRowMarkRel(relation, rc->markType);
901
902 erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
903 erm->relation = relation;
904 erm->relid = relid;
905 erm->rti = rc->rti;
906 erm->prti = rc->prti;
907 erm->rowmarkId = rc->rowmarkId;
908 erm->markType = rc->markType;
909 erm->strength = rc->strength;
910 erm->waitPolicy = rc->waitPolicy;
911 erm->ermActive = false;
913 erm->ermExtra = NULL;
914
915 Assert(erm->rti > 0 && erm->rti <= estate->es_range_table_size &&
916 estate->es_rowmarks[erm->rti - 1] == NULL);
917
918 estate->es_rowmarks[erm->rti - 1] = erm;
919 }
920 }
921
922 /*
923 * Initialize the executor's tuple table to empty.
924 */
925 estate->es_tupleTable = NIL;
926
927 /* signal that this EState is not used for EPQ */
928 estate->es_epq_active = NULL;
929
930 /*
931 * Initialize private state information for each SubPlan. We must do this
932 * before running ExecInitNode on the main query tree, since
933 * ExecInitSubPlan expects to be able to find these entries.
934 */
935 Assert(estate->es_subplanstates == NIL);
936 i = 1; /* subplan indices count from 1 */
937 foreach(l, plannedstmt->subplans)
938 {
939 Plan *subplan = (Plan *) lfirst(l);
940 PlanState *subplanstate;
941 int sp_eflags;
942
943 /*
944 * A subplan will never need to do BACKWARD scan nor MARK/RESTORE. If
945 * it is a parameterless subplan (not initplan), we suggest that it be
946 * prepared to handle REWIND efficiently; otherwise there is no need.
947 */
948 sp_eflags = eflags
950 if (bms_is_member(i, plannedstmt->rewindPlanIDs))
951 sp_eflags |= EXEC_FLAG_REWIND;
952
953 subplanstate = ExecInitNode(subplan, estate, sp_eflags);
954
955 estate->es_subplanstates = lappend(estate->es_subplanstates,
956 subplanstate);
957
958 i++;
959 }
960
961 /*
962 * Initialize the private state information for all the nodes in the query
963 * tree. This opens files, allocates storage and leaves us ready to start
964 * processing tuples.
965 */
966 planstate = ExecInitNode(plan, estate, eflags);
967
968 /*
969 * Get the tuple descriptor describing the type of tuples to return.
970 */
971 tupType = ExecGetResultType(planstate);
972
973 /*
974 * Initialize the junk filter if needed. SELECT queries need a filter if
975 * there are any junk attrs in the top-level tlist.
976 */
977 if (operation == CMD_SELECT)
978 {
979 bool junk_filter_needed = false;
980 ListCell *tlist;
981
982 foreach(tlist, plan->targetlist)
983 {
984 TargetEntry *tle = (TargetEntry *) lfirst(tlist);
985
986 if (tle->resjunk)
987 {
988 junk_filter_needed = true;
989 break;
990 }
991 }
992
993 if (junk_filter_needed)
994 {
995 JunkFilter *j;
996 TupleTableSlot *slot;
997
998 slot = ExecInitExtraTupleSlot(estate, NULL, &TTSOpsVirtual);
999 j = ExecInitJunkFilter(planstate->plan->targetlist,
1000 slot);
1001 estate->es_junkFilter = j;
1002
1003 /* Want to return the cleaned tuple type */
1004 tupType = j->jf_cleanTupType;
1005 }
1006 }
1007
1008 queryDesc->tupDesc = tupType;
1009 queryDesc->planstate = planstate;
1010}
JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
Definition: execJunk.c:60
static void CheckValidRowMarkRel(Relation rel, RowMarkType markType)
Definition: execMain.c:1138
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
Definition: execMain.c:579
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2018
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:495
void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos)
Definition: execUtils.c:773
Relation ExecGetRangeTableRelation(EState *estate, Index rti)
Definition: execUtils.c:807
#define EXEC_FLAG_REWIND
Definition: executor.h:67
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:603
#define EXEC_FLAG_MARK
Definition: executor.h:69
int j
Definition: isn.c:73
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
void * palloc(Size size)
Definition: mcxt.c:1317
CmdType
Definition: nodes.h:263
#define plan(x)
Definition: pg_regress.c:161
@ ROW_MARK_SHARE
Definition: plannodes.h:1331
@ ROW_MARK_EXCLUSIVE
Definition: plannodes.h:1329
@ ROW_MARK_NOKEYEXCLUSIVE
Definition: plannodes.h:1330
@ ROW_MARK_KEYSHARE
Definition: plannodes.h:1332
ItemPointerData curCtid
Definition: execnodes.h:787
LockClauseStrength strength
Definition: execnodes.h:784
bool ermActive
Definition: execnodes.h:786
LockWaitPolicy waitPolicy
Definition: execnodes.h:785
void * ermExtra
Definition: execnodes.h:788
LockClauseStrength strength
Definition: plannodes.h:1387
Index prti
Definition: plannodes.h:1383
RowMarkType markType
Definition: plannodes.h:1385
LockWaitPolicy waitPolicy
Definition: plannodes.h:1388
bool isParent
Definition: plannodes.h:1389
Index rowmarkId
Definition: plannodes.h:1384
List * targetlist
Definition: plannodes.h:153
struct Plan * planTree
Definition: plannodes.h:70
List * rowMarks
Definition: plannodes.h:87
Bitmapset * rewindPlanIDs
Definition: plannodes.h:85
List * rtable
Definition: plannodes.h:72
TupleDesc tupDesc
Definition: execdesc.h:47

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_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, exec_rt_fetch(), ExecCheckPermissions(), ExecGetRangeTableRelation(), ExecGetResultType(), ExecInitExtraTupleSlot(), ExecInitJunkFilter(), ExecInitNode(), ExecInitRangeTable(), i, PlanRowMark::isParent, ItemPointerSetInvalid(), j, lappend(), lfirst, ExecRowMark::markType, PlanRowMark::markType, NIL, QueryDesc::operation, palloc(), palloc0(), PlannedStmt::permInfos, PlanState::plan, plan, QueryDesc::plannedstmt, QueryDesc::planstate, PlannedStmt::planTree, ExecRowMark::prti, PlanRowMark::prti, ExecRowMark::relation, ExecRowMark::relid, RangeTblEntry::relid, 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, PlannedStmt::subplans, Plan::targetlist, TTSOpsVirtual, QueryDesc::tupDesc, ExecRowMark::waitPolicy, and PlanRowMark::waitPolicy.

Referenced by standard_ExecutorStart().

◆ InitResultRelInfo()

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

Definition at line 1203 of file execMain.c.

1208{
1209 MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1210 resultRelInfo->type = T_ResultRelInfo;
1211 resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1212 resultRelInfo->ri_RelationDesc = resultRelationDesc;
1213 resultRelInfo->ri_NumIndices = 0;
1214 resultRelInfo->ri_IndexRelationDescs = NULL;
1215 resultRelInfo->ri_IndexRelationInfo = NULL;
1216 resultRelInfo->ri_needLockTagTuple =
1217 IsInplaceUpdateRelation(resultRelationDesc);
1218 /* make a copy so as not to depend on relcache info not changing... */
1219 resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1220 if (resultRelInfo->ri_TrigDesc)
1221 {
1222 int n = resultRelInfo->ri_TrigDesc->numtriggers;
1223
1224 resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1225 palloc0(n * sizeof(FmgrInfo));
1226 resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1227 palloc0(n * sizeof(ExprState *));
1228 if (instrument_options)
1229 resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options, false);
1230 }
1231 else
1232 {
1233 resultRelInfo->ri_TrigFunctions = NULL;
1234 resultRelInfo->ri_TrigWhenExprs = NULL;
1235 resultRelInfo->ri_TrigInstrument = NULL;
1236 }
1237 if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1238 resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
1239 else
1240 resultRelInfo->ri_FdwRoutine = NULL;
1241
1242 /* The following fields are set later if needed */
1243 resultRelInfo->ri_RowIdAttNo = 0;
1244 resultRelInfo->ri_extraUpdatedCols = NULL;
1245 resultRelInfo->ri_projectNew = NULL;
1246 resultRelInfo->ri_newTupleSlot = NULL;
1247 resultRelInfo->ri_oldTupleSlot = NULL;
1248 resultRelInfo->ri_projectNewInfoValid = false;
1249 resultRelInfo->ri_FdwState = NULL;
1250 resultRelInfo->ri_usesFdwDirectModify = false;
1251 resultRelInfo->ri_ConstraintExprs = NULL;
1252 resultRelInfo->ri_GeneratedExprsI = NULL;
1253 resultRelInfo->ri_GeneratedExprsU = NULL;
1254 resultRelInfo->ri_projectReturning = NULL;
1255 resultRelInfo->ri_onConflictArbiterIndexes = NIL;
1256 resultRelInfo->ri_onConflict = NULL;
1257 resultRelInfo->ri_ReturningSlot = NULL;
1258 resultRelInfo->ri_TrigOldSlot = NULL;
1259 resultRelInfo->ri_TrigNewSlot = NULL;
1260 resultRelInfo->ri_AllNullSlot = NULL;
1261 resultRelInfo->ri_MergeActions[MERGE_WHEN_MATCHED] = NIL;
1264 resultRelInfo->ri_MergeJoinCondition = NULL;
1265
1266 /*
1267 * Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
1268 * non-NULL partition_root_rri. For child relations that are part of the
1269 * initial query rather than being dynamically added by tuple routing,
1270 * this field is filled in ExecInitModifyTable().
1271 */
1272 resultRelInfo->ri_RootResultRelInfo = partition_root_rri;
1273 /* Set by ExecGetRootToChildMap */
1274 resultRelInfo->ri_RootToChildMap = NULL;
1275 resultRelInfo->ri_RootToChildMapValid = false;
1276 /* Set by ExecInitRoutingInfo */
1277 resultRelInfo->ri_PartitionTupleSlot = NULL;
1278 resultRelInfo->ri_ChildToRootMap = NULL;
1279 resultRelInfo->ri_ChildToRootMapValid = false;
1280 resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
1281}
#define MemSet(start, val, len)
Definition: c.h:977
Instrumentation * InstrAlloc(int n, int instrument_options, bool async_mode)
Definition: instrument.c:31
@ MERGE_WHEN_NOT_MATCHED_BY_TARGET
Definition: primnodes.h:2029
@ MERGE_WHEN_NOT_MATCHED_BY_SOURCE
Definition: primnodes.h:2028
@ MERGE_WHEN_MATCHED
Definition: primnodes.h:2027
Definition: fmgr.h:57
TriggerDesc * trigdesc
Definition: rel.h:117
TupleConversionMap * ri_RootToChildMap
Definition: execnodes.h:592
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:607
bool ri_projectNewInfoValid
Definition: execnodes.h:501
OnConflictSetState * ri_onConflict
Definition: execnodes.h:569
List * ri_onConflictArbiterIndexes
Definition: execnodes.h:566
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:516
ExprState * ri_MergeJoinCondition
Definition: execnodes.h:575
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:480
TupleTableSlot * ri_ReturningSlot
Definition: execnodes.h:519
TupleTableSlot * ri_oldTupleSlot
Definition: execnodes.h:499
bool ri_RootToChildMapValid
Definition: execnodes.h:593
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:610
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:507
TupleTableSlot * ri_AllNullSlot
Definition: execnodes.h:522
Bitmapset * ri_extraUpdatedCols
Definition: execnodes.h:492
ExprState ** ri_GeneratedExprsI
Definition: execnodes.h:552
TupleConversionMap * ri_ChildToRootMap
Definition: execnodes.h:586
void * ri_FdwState
Definition: execnodes.h:528
bool ri_ChildToRootMapValid
Definition: execnodes.h:587
List * ri_MergeActions[NUM_MERGE_MATCH_KINDS]
Definition: execnodes.h:572
TupleTableSlot * ri_newTupleSlot
Definition: execnodes.h:497
ProjectionInfo * ri_projectNew
Definition: execnodes.h:495
NodeTag type
Definition: execnodes.h:468
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:563
ExprState ** ri_GeneratedExprsU
Definition: execnodes.h:553
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:513
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:510
bool ri_usesFdwDirectModify
Definition: execnodes.h:531
AttrNumber ri_RowIdAttNo
Definition: execnodes.h:489
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:483
TupleTableSlot * ri_TrigNewSlot
Definition: execnodes.h:521
TupleTableSlot * ri_TrigOldSlot
Definition: execnodes.h:520
int numtriggers
Definition: reltrigger.h:50
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:2087

References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), IsInplaceUpdateRelation(), MemSet, MERGE_WHEN_MATCHED, MERGE_WHEN_NOT_MATCHED_BY_SOURCE, MERGE_WHEN_NOT_MATCHED_BY_TARGET, NIL, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, ResultRelInfo::ri_AllNullSlot, ResultRelInfo::ri_ChildToRootMap, ResultRelInfo::ri_ChildToRootMapValid, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_extraUpdatedCols, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_GeneratedExprsI, ResultRelInfo::ri_GeneratedExprsU, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_MergeActions, ResultRelInfo::ri_MergeJoinCondition, ResultRelInfo::ri_needLockTagTuple, 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_RootToChildMap, ResultRelInfo::ri_RootToChildMapValid, ResultRelInfo::ri_RowIdAttNo, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, ResultRelInfo::ri_TrigNewSlot, ResultRelInfo::ri_TrigOldSlot, ResultRelInfo::ri_TrigWhenExprs, ResultRelInfo::ri_usesFdwDirectModify, RelationData::trigdesc, and ResultRelInfo::type.

Referenced by create_edata_for_relation(), ExecGetAncestorResultRels(), ExecGetTriggerResultRel(), ExecInitPartitionDispatchInfo(), ExecInitPartitionInfo(), ExecInitResultRelation(), and ExecuteTruncateGuts().

◆ standard_ExecutorEnd()

void standard_ExecutorEnd ( QueryDesc queryDesc)

Definition at line 472 of file execMain.c.

473{
474 EState *estate;
475 MemoryContext oldcontext;
476
477 /* sanity checks */
478 Assert(queryDesc != NULL);
479
480 estate = queryDesc->estate;
481
482 Assert(estate != NULL);
483
484 if (estate->es_parallel_workers_to_launch > 0)
487
488 /*
489 * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This
490 * Assert is needed because ExecutorFinish is new as of 9.1, and callers
491 * might forget to call it.
492 */
493 Assert(estate->es_finished ||
495
496 /*
497 * Switch into per-query memory context to run ExecEndPlan
498 */
499 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
500
501 ExecEndPlan(queryDesc->planstate, estate);
502
503 /* do away with our snapshots */
506
507 /*
508 * Must switch out of context before destroying it
509 */
510 MemoryContextSwitchTo(oldcontext);
511
512 /*
513 * Release EState and per-query memory context. This should release
514 * everything the executor has allocated.
515 */
516 FreeExecutorState(estate);
517
518 /* Reset queryDesc fields that no longer point to anything */
519 queryDesc->tupDesc = NULL;
520 queryDesc->estate = NULL;
521 queryDesc->planstate = NULL;
522 queryDesc->totaltime = NULL;
523}
static void ExecEndPlan(PlanState *planstate, EState *estate)
Definition: execMain.c:1485
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:65
int64 PgStat_Counter
Definition: pgstat.h:66
void pgstat_update_parallel_workers_stats(PgStat_Counter workers_to_launch, PgStat_Counter workers_launched)
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:794
int es_parallel_workers_to_launch
Definition: execnodes.h:727
bool es_finished
Definition: execnodes.h:702
int es_parallel_workers_launched
Definition: execnodes.h:729
struct Instrumentation * totaltime
Definition: execdesc.h:55

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

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

◆ standard_ExecutorFinish()

void standard_ExecutorFinish ( QueryDesc queryDesc)

Definition at line 412 of file execMain.c.

413{
414 EState *estate;
415 MemoryContext oldcontext;
416
417 /* sanity checks */
418 Assert(queryDesc != NULL);
419
420 estate = queryDesc->estate;
421
422 Assert(estate != NULL);
424
425 /* This should be run once and only once per Executor instance */
426 Assert(!estate->es_finished);
427
428 /* Switch into per-query memory context */
429 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
430
431 /* Allow instrumentation of Executor overall runtime */
432 if (queryDesc->totaltime)
433 InstrStartNode(queryDesc->totaltime);
434
435 /* Run ModifyTable nodes to completion */
436 ExecPostprocessPlan(estate);
437
438 /* Execute queued AFTER triggers, unless told not to */
439 if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
440 AfterTriggerEndQuery(estate);
441
442 if (queryDesc->totaltime)
443 InstrStopNode(queryDesc->totaltime, 0);
444
445 MemoryContextSwitchTo(oldcontext);
446
447 estate->es_finished = true;
448}
static void ExecPostprocessPlan(EState *estate)
Definition: execMain.c:1439
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:70
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:68
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:84
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:5045

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

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

◆ standard_ExecutorRun()

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

Definition at line 304 of file execMain.c.

306{
307 EState *estate;
308 CmdType operation;
310 bool sendTuples;
311 MemoryContext oldcontext;
312
313 /* sanity checks */
314 Assert(queryDesc != NULL);
315
316 estate = queryDesc->estate;
317
318 Assert(estate != NULL);
320
321 /* caller must ensure the query's snapshot is active */
323
324 /*
325 * Switch into per-query memory context
326 */
327 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
328
329 /* Allow instrumentation of Executor overall runtime */
330 if (queryDesc->totaltime)
331 InstrStartNode(queryDesc->totaltime);
332
333 /*
334 * extract information from the query descriptor and the query feature.
335 */
336 operation = queryDesc->operation;
337 dest = queryDesc->dest;
338
339 /*
340 * startup tuple receiver, if we will be emitting tuples
341 */
342 estate->es_processed = 0;
343
344 sendTuples = (operation == CMD_SELECT ||
345 queryDesc->plannedstmt->hasReturning);
346
347 if (sendTuples)
348 dest->rStartup(dest, operation, queryDesc->tupDesc);
349
350 /*
351 * Run plan, unless direction is NoMovement.
352 *
353 * Note: pquery.c selects NoMovement if a prior call already reached
354 * end-of-data in the user-specified fetch direction. This is important
355 * because various parts of the executor can misbehave if called again
356 * after reporting EOF. For example, heapam.c would actually restart a
357 * heapscan and return all its data afresh. There is also some doubt
358 * about whether a parallel plan would operate properly if an additional,
359 * necessarily non-parallel execution request occurs after completing a
360 * parallel execution. (That case should work, but it's untested.)
361 */
362 if (!ScanDirectionIsNoMovement(direction))
363 ExecutePlan(queryDesc,
364 operation,
365 sendTuples,
366 count,
367 direction,
368 dest);
369
370 /*
371 * Update es_total_processed to keep track of the number of tuples
372 * processed across multiple ExecutorRun() calls.
373 */
374 estate->es_total_processed += estate->es_processed;
375
376 /*
377 * shutdown tuple receiver, if we started it
378 */
379 if (sendTuples)
380 dest->rShutdown(dest);
381
382 if (queryDesc->totaltime)
383 InstrStopNode(queryDesc->totaltime, estate->es_processed);
384
385 MemoryContextSwitchTo(oldcontext);
386}
static void ExecutePlan(QueryDesc *queryDesc, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, DestReceiver *dest)
Definition: execMain.c:1605
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:57
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:728
uint64 es_total_processed
Definition: execnodes.h:697
bool hasReturning
Definition: plannodes.h:56
DestReceiver * dest
Definition: execdesc.h:41

References Assert, CMD_SELECT, generate_unaccent_rules::dest, QueryDesc::dest, EState::es_processed, EState::es_query_cxt, EState::es_snapshot, EState::es_top_eflags, EState::es_total_processed, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecutePlan(), GetActiveSnapshot(), PlannedStmt::hasReturning, InstrStartNode(), InstrStopNode(), MemoryContextSwitchTo(), QueryDesc::operation, QueryDesc::plannedstmt, ScanDirectionIsNoMovement, QueryDesc::totaltime, and QueryDesc::tupDesc.

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

◆ standard_ExecutorStart()

void standard_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 138 of file execMain.c.

139{
140 EState *estate;
141 MemoryContext oldcontext;
142
143 /* sanity checks: queryDesc must not be started already */
144 Assert(queryDesc != NULL);
145 Assert(queryDesc->estate == NULL);
146
147 /* caller must ensure the query's snapshot is active */
148 Assert(GetActiveSnapshot() == queryDesc->snapshot);
149
150 /*
151 * If the transaction is read-only, we need to check if any writes are
152 * planned to non-temporary tables. EXPLAIN is considered read-only.
153 *
154 * Don't allow writes in parallel mode. Supporting UPDATE and DELETE
155 * would require (a) storing the combo CID hash in shared memory, rather
156 * than synchronizing it just once at the start of parallelism, and (b) an
157 * alternative to heap_update()'s reliance on xmax for mutual exclusion.
158 * INSERT may have no such troubles, but we forbid it to simplify the
159 * checks.
160 *
161 * We have lower-level defenses in CommandCounterIncrement and elsewhere
162 * against performing unsafe operations in parallel mode, but this gives a
163 * more user-friendly error message.
164 */
165 if ((XactReadOnly || IsInParallelMode()) &&
166 !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
168
169 /*
170 * Build EState, switch into per-query memory context for startup.
171 */
172 estate = CreateExecutorState();
173 queryDesc->estate = estate;
174
175 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
176
177 /*
178 * Fill in external parameters, if any, from queryDesc; and allocate
179 * workspace for internal parameters
180 */
181 estate->es_param_list_info = queryDesc->params;
182
183 if (queryDesc->plannedstmt->paramExecTypes != NIL)
184 {
185 int nParamExec;
186
187 nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes);
189 palloc0(nParamExec * sizeof(ParamExecData));
190 }
191
192 /* We now require all callers to provide sourceText */
193 Assert(queryDesc->sourceText != NULL);
194 estate->es_sourceText = queryDesc->sourceText;
195
196 /*
197 * Fill in the query environment, if any, from queryDesc.
198 */
199 estate->es_queryEnv = queryDesc->queryEnv;
200
201 /*
202 * If non-read-only query, set the command ID to mark output tuples with
203 */
204 switch (queryDesc->operation)
205 {
206 case CMD_SELECT:
207
208 /*
209 * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark
210 * tuples
211 */
212 if (queryDesc->plannedstmt->rowMarks != NIL ||
213 queryDesc->plannedstmt->hasModifyingCTE)
214 estate->es_output_cid = GetCurrentCommandId(true);
215
216 /*
217 * A SELECT without modifying CTEs can't possibly queue triggers,
218 * so force skip-triggers mode. This is just a marginal efficiency
219 * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't
220 * all that expensive, but we might as well do it.
221 */
222 if (!queryDesc->plannedstmt->hasModifyingCTE)
223 eflags |= EXEC_FLAG_SKIP_TRIGGERS;
224 break;
225
226 case CMD_INSERT:
227 case CMD_DELETE:
228 case CMD_UPDATE:
229 case CMD_MERGE:
230 estate->es_output_cid = GetCurrentCommandId(true);
231 break;
232
233 default:
234 elog(ERROR, "unrecognized operation code: %d",
235 (int) queryDesc->operation);
236 break;
237 }
238
239 /*
240 * Copy other important information into the EState
241 */
242 estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot);
244 estate->es_top_eflags = eflags;
245 estate->es_instrument = queryDesc->instrument_options;
246 estate->es_jit_flags = queryDesc->plannedstmt->jitFlags;
247
248 /*
249 * Set up an AFTER-trigger statement context, unless told not to, or
250 * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called).
251 */
254
255 /*
256 * Initialize the plan state tree
257 */
258 InitPlan(queryDesc, eflags);
259
260 MemoryContextSwitchTo(oldcontext);
261}
static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
Definition: execMain.c:799
static void InitPlan(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:833
@ CMD_MERGE
Definition: nodes.h:269
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:752
int es_jit_flags
Definition: execnodes.h:744
const char * es_sourceText
Definition: execnodes.h:658
int jitFlags
Definition: plannodes.h:68
const char * sourceText
Definition: execdesc.h:38
ParamListInfo params
Definition: execdesc.h:42
int instrument_options
Definition: execdesc.h:44
Snapshot snapshot
Definition: execdesc.h:39
QueryEnvironment * queryEnv
Definition: execdesc.h:43
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
void AfterTriggerBeginQuery(void)
Definition: trigger.c:5025
bool XactReadOnly
Definition: xact.c:81
bool IsInParallelMode(void)
Definition: xact.c:1088
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:828

References AfterTriggerBeginQuery(), Assert, CMD_DELETE, CMD_INSERT, CMD_MERGE, 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(), GetActiveSnapshot(), GetCurrentCommandId(), PlannedStmt::hasModifyingCTE, InitPlan(), QueryDesc::instrument_options, IsInParallelMode(), PlannedStmt::jitFlags, list_length(), MemoryContextSwitchTo(), NIL, QueryDesc::operation, palloc0(), PlannedStmt::paramExecTypes, QueryDesc::params, QueryDesc::plannedstmt, QueryDesc::queryEnv, RegisterSnapshot(), PlannedStmt::rowMarks, QueryDesc::snapshot, QueryDesc::sourceText, and XactReadOnly.

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

Variable Documentation

◆ ExecutorCheckPerms_hook

ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL

Definition at line 73 of file execMain.c.

Referenced by _PG_init(), and ExecCheckPermissions().

◆ ExecutorEnd_hook

ExecutorEnd_hook_type ExecutorEnd_hook = NULL

Definition at line 70 of file execMain.c.

Referenced by _PG_init(), and ExecutorEnd().

◆ ExecutorFinish_hook

ExecutorFinish_hook_type ExecutorFinish_hook = NULL

Definition at line 69 of file execMain.c.

Referenced by _PG_init(), and ExecutorFinish().

◆ ExecutorRun_hook

ExecutorRun_hook_type ExecutorRun_hook = NULL

Definition at line 68 of file execMain.c.

Referenced by _PG_init(), and ExecutorRun().

◆ ExecutorStart_hook

ExecutorStart_hook_type ExecutorStart_hook = NULL

Definition at line 67 of file execMain.c.

Referenced by _PG_init(), and ExecutorStart().