PostgreSQL Source Code  git master
executor.h File Reference
#include "executor/execdesc.h"
#include "fmgr.h"
#include "nodes/lockoptions.h"
#include "nodes/parsenodes.h"
#include "utils/memutils.h"
Include dependency graph for executor.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  TupOutputState
 

Macros

#define EXEC_FLAG_EXPLAIN_ONLY   0x0001 /* EXPLAIN, no ANALYZE */
 
#define EXEC_FLAG_REWIND   0x0002 /* need efficient rescan */
 
#define EXEC_FLAG_BACKWARD   0x0004 /* need backward scan */
 
#define EXEC_FLAG_MARK   0x0008 /* need mark/restore */
 
#define EXEC_FLAG_SKIP_TRIGGERS   0x0010 /* skip AfterTrigger calls */
 
#define EXEC_FLAG_WITH_NO_DATA   0x0020 /* rel scannability doesn't matter */
 
#define EvalPlanQualSetSlot(epqstate, slot)   ((epqstate)->origslot = (slot))
 
#define do_text_output_oneline(tstate, str_to_emit)
 
#define ResetExprContext(econtext)   MemoryContextReset((econtext)->ecxt_per_tuple_memory)
 
#define GetPerTupleExprContext(estate)
 
#define GetPerTupleMemoryContext(estate)   (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
 
#define ResetPerTupleExprContext(estate)
 

Typedefs

typedef void(* ExecutorStart_hook_type) (QueryDesc *queryDesc, int eflags)
 
typedef void(* ExecutorRun_hook_type) (QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
 
typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)
 
typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)
 
typedef bool(* ExecutorCheckPerms_hook_type) (List *, bool)
 
typedef TupleTableSlot *(* ExecScanAccessMtd) (ScanState *node)
 
typedef bool(* ExecScanRecheckMtd) (ScanState *node, TupleTableSlot *slot)
 
typedef struct TupOutputState TupOutputState
 

Functions

void ExecReScan (PlanState *node)
 
void ExecMarkPos (PlanState *node)
 
void ExecRestrPos (PlanState *node)
 
bool ExecSupportsMarkRestore (struct Path *pathnode)
 
bool ExecSupportsBackwardScan (Plan *node)
 
bool ExecMaterializesOutput (NodeTag plantype)
 
bool execCurrentOf (CurrentOfExpr *cexpr, ExprContext *econtext, Oid table_oid, ItemPointer current_tid)
 
ExprStateexecTuplesMatchPrepare (TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
 
void execTuplesHashPrepare (int numCols, const Oid *eqOperators, Oid **eqFuncOids, FmgrInfo **hashFunctions)
 
TupleHashTable BuildTupleHashTable (PlanState *parent, TupleDesc inputDesc, int numCols, AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
 
TupleHashTable BuildTupleHashTableExt (PlanState *parent, TupleDesc inputDesc, int numCols, AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, long nbuckets, Size additionalsize, MemoryContext metacxt, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
 
TupleHashEntry LookupTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
 
uint32 TupleHashTableHash (TupleHashTable hashtable, TupleTableSlot *slot)
 
TupleHashEntry LookupTupleHashEntryHash (TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 hash)
 
TupleHashEntry FindTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, ExprState *eqcomp, FmgrInfo *hashfunctions)
 
void ResetTupleHashTable (TupleHashTable hashtable)
 
JunkFilterExecInitJunkFilter (List *targetList, TupleTableSlot *slot)
 
JunkFilterExecInitJunkFilterConversion (List *targetList, TupleDesc cleanTupType, TupleTableSlot *slot)
 
AttrNumber ExecFindJunkAttribute (JunkFilter *junkfilter, const char *attrName)
 
AttrNumber ExecFindJunkAttributeInTlist (List *targetlist, const char *attrName)
 
Datum ExecGetJunkAttribute (TupleTableSlot *slot, AttrNumber attno, bool *isNull)
 
TupleTableSlotExecFilterJunk (JunkFilter *junkfilter, TupleTableSlot *slot)
 
void ExecutorStart (QueryDesc *queryDesc, int eflags)
 
void standard_ExecutorStart (QueryDesc *queryDesc, int eflags)
 
void ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
 
void standard_ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
 
void ExecutorFinish (QueryDesc *queryDesc)
 
void standard_ExecutorFinish (QueryDesc *queryDesc)
 
void ExecutorEnd (QueryDesc *queryDesc)
 
void standard_ExecutorEnd (QueryDesc *queryDesc)
 
void ExecutorRewind (QueryDesc *queryDesc)
 
bool ExecCheckRTPerms (List *rangeTable, bool ereport_on_violation)
 
void CheckValidResultRel (ResultRelInfo *resultRelInfo, CmdType operation)
 
void InitResultRelInfo (ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
 
ResultRelInfoExecGetTriggerResultRel (EState *estate, Oid relid)
 
void ExecCleanUpTriggerState (EState *estate)
 
void ExecConstraints (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 ExecWithCheckOptions (WCOKind kind, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
LockTupleMode ExecUpdateLockMode (EState *estate, ResultRelInfo *relinfo)
 
ExecRowMarkExecFindRowMark (EState *estate, Index rti, bool missing_ok)
 
ExecAuxRowMarkExecBuildAuxRowMark (ExecRowMark *erm, List *targetlist)
 
TupleTableSlotEvalPlanQual (EPQState *epqstate, Relation relation, Index rti, TupleTableSlot *testslot)
 
void EvalPlanQualInit (EPQState *epqstate, EState *parentestate, Plan *subplan, List *auxrowmarks, int epqParam)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
TupleTableSlotEvalPlanQualSlot (EPQState *epqstate, Relation relation, Index rti)
 
bool EvalPlanQualFetchRowMark (EPQState *epqstate, Index rti, TupleTableSlot *slot)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate)
 
void EvalPlanQualEnd (EPQState *epqstate)
 
PlanStateExecInitNode (Plan *node, EState *estate, int eflags)
 
void ExecSetExecProcNode (PlanState *node, ExecProcNodeMtd function)
 
NodeMultiExecProcNode (PlanState *node)
 
void ExecEndNode (PlanState *node)
 
bool ExecShutdownNode (PlanState *node)
 
void ExecSetTupleBound (int64 tuples_needed, PlanState *child_node)
 
static TupleTableSlotExecProcNode (PlanState *node)
 
ExprStateExecInitExpr (Expr *node, PlanState *parent)
 
ExprStateExecInitExprWithParams (Expr *node, ParamListInfo ext_params)
 
ExprStateExecInitQual (List *qual, PlanState *parent)
 
ExprStateExecInitCheck (List *qual, PlanState *parent)
 
ListExecInitExprList (List *nodes, PlanState *parent)
 
ExprStateExecBuildAggTrans (AggState *aggstate, struct AggStatePerPhaseData *phase, bool doSort, bool doHash, bool nullcheck)
 
ExprStateExecBuildGroupingEqual (TupleDesc ldesc, TupleDesc rdesc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, int numCols, const AttrNumber *keyColIdx, const Oid *eqfunctions, const Oid *collations, PlanState *parent)
 
ProjectionInfoExecBuildProjectionInfo (List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
 
ExprStateExecPrepareExpr (Expr *node, EState *estate)
 
ExprStateExecPrepareQual (List *qual, EState *estate)
 
ExprStateExecPrepareCheck (List *qual, EState *estate)
 
ListExecPrepareExprList (List *nodes, EState *estate)
 
static Datum ExecEvalExpr (ExprState *state, ExprContext *econtext, bool *isNull)
 
static Datum ExecEvalExprSwitchContext (ExprState *state, ExprContext *econtext, bool *isNull)
 
static TupleTableSlotExecProject (ProjectionInfo *projInfo)
 
static bool ExecQual (ExprState *state, ExprContext *econtext)
 
static bool ExecQualAndReset (ExprState *state, ExprContext *econtext)
 
bool ExecCheck (ExprState *state, ExprContext *context)
 
SetExprStateExecInitTableFunctionResult (Expr *expr, ExprContext *econtext, PlanState *parent)
 
TuplestorestateExecMakeTableFunctionResult (SetExprState *setexpr, ExprContext *econtext, MemoryContext argContext, TupleDesc expectedDesc, bool randomAccess)
 
SetExprStateExecInitFunctionResultSet (Expr *expr, ExprContext *econtext, PlanState *parent)
 
Datum ExecMakeFunctionResultSet (SetExprState *fcache, ExprContext *econtext, MemoryContext argContext, bool *isNull, ExprDoneCond *isDone)
 
TupleTableSlotExecScan (ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
 
void ExecAssignScanProjectionInfo (ScanState *node)
 
void ExecAssignScanProjectionInfoWithVarno (ScanState *node, Index varno)
 
void ExecScanReScan (ScanState *node)
 
void ExecInitResultTypeTL (PlanState *planstate)
 
void ExecInitResultSlot (PlanState *planstate, const TupleTableSlotOps *tts_ops)
 
void ExecInitResultTupleSlotTL (PlanState *planstate, const TupleTableSlotOps *tts_ops)
 
void ExecInitScanTupleSlot (EState *estate, ScanState *scanstate, TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
 
TupleTableSlotExecInitExtraTupleSlot (EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
 
TupleTableSlotExecInitNullTupleSlot (EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
 
TupleDesc ExecTypeFromTL (List *targetList)
 
TupleDesc ExecCleanTypeFromTL (List *targetList)
 
TupleDesc ExecTypeFromExprList (List *exprList)
 
void ExecTypeSetColNames (TupleDesc typeInfo, List *namesList)
 
void UpdateChangedParamSet (PlanState *node, Bitmapset *newchg)
 
TupOutputStatebegin_tup_output_tupdesc (DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
 
void do_tup_output (TupOutputState *tstate, Datum *values, bool *isnull)
 
void do_text_output_multiline (TupOutputState *tstate, const char *txt)
 
void end_tup_output (TupOutputState *tstate)
 
EStateCreateExecutorState (void)
 
void FreeExecutorState (EState *estate)
 
ExprContextCreateExprContext (EState *estate)
 
ExprContextCreateWorkExprContext (EState *estate)
 
ExprContextCreateStandaloneExprContext (void)
 
void FreeExprContext (ExprContext *econtext, bool isCommit)
 
void ReScanExprContext (ExprContext *econtext)
 
ExprContextMakePerTupleExprContext (EState *estate)
 
void ExecAssignExprContext (EState *estate, PlanState *planstate)
 
TupleDesc ExecGetResultType (PlanState *planstate)
 
const TupleTableSlotOpsExecGetResultSlotOps (PlanState *planstate, bool *isfixed)
 
void ExecAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc)
 
void ExecConditionalAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc, Index varno)
 
void ExecFreeExprContext (PlanState *planstate)
 
void ExecAssignScanType (ScanState *scanstate, TupleDesc tupDesc)
 
void ExecCreateScanSlotFromOuterPlan (EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
 
bool ExecRelationIsTargetRelation (EState *estate, Index scanrelid)
 
Relation ExecOpenScanRelation (EState *estate, Index scanrelid, int eflags)
 
void ExecInitRangeTable (EState *estate, List *rangeTable)
 
static RangeTblEntryexec_rt_fetch (Index rti, EState *estate)
 
Relation ExecGetRangeTableRelation (EState *estate, Index rti)
 
int executor_errposition (EState *estate, int location)
 
void RegisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
void UnregisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
Datum GetAttributeByName (HeapTupleHeader tuple, const char *attname, bool *isNull)
 
Datum GetAttributeByNum (HeapTupleHeader tuple, AttrNumber attrno, bool *isNull)
 
int ExecTargetListLength (List *targetlist)
 
int ExecCleanTargetListLength (List *targetlist)
 
TupleTableSlotExecGetTriggerOldSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleTableSlotExecGetTriggerNewSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleTableSlotExecGetReturningSlot (EState *estate, ResultRelInfo *relInfo)
 
void ExecOpenIndices (ResultRelInfo *resultRelInfo, bool speculative)
 
void ExecCloseIndices (ResultRelInfo *resultRelInfo)
 
ListExecInsertIndexTuples (TupleTableSlot *slot, EState *estate, bool noDupErr, bool *specConflict, List *arbiterIndexes)
 
bool ExecCheckIndexConstraints (TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, List *arbiterIndexes)
 
void check_exclusion_constraint (Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex)
 
bool RelationFindReplTupleByIndex (Relation rel, Oid idxoid, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
bool RelationFindReplTupleSeq (Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
void ExecSimpleRelationInsert (EState *estate, TupleTableSlot *slot)
 
void ExecSimpleRelationUpdate (EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot)
 
void ExecSimpleRelationDelete (EState *estate, EPQState *epqstate, TupleTableSlot *searchslot)
 
void CheckCmdReplicaIdentity (Relation rel, CmdType cmd)
 
void CheckSubscriptionRelkind (char relkind, const char *nspname, const char *relname)
 

Variables

PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook
 
PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook
 
PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook
 
PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook
 
PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
 

Macro Definition Documentation

◆ do_text_output_oneline

#define do_text_output_oneline (   tstate,
  str_to_emit 
)
Value:
do { \
Datum values_[1]; \
bool isnull_[1]; \
values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
isnull_[0] = false; \
do_tup_output(tstate, values_, isnull_); \
pfree(DatumGetPointer(values_[0])); \
} while (0)
#define PointerGetDatum(X)
Definition: postgres.h:556
text * cstring_to_text(const char *s)
Definition: varlena.c:172
#define DatumGetPointer(X)
Definition: postgres.h:549

Definition at line 479 of file executor.h.

Referenced by ExplainQuery(), and ShowGUCConfigOption().

◆ EvalPlanQualSetSlot

#define EvalPlanQualSetSlot (   epqstate,
  slot 
)    ((epqstate)->origslot = (slot))

◆ EXEC_FLAG_BACKWARD

◆ EXEC_FLAG_EXPLAIN_ONLY

◆ EXEC_FLAG_MARK

◆ EXEC_FLAG_REWIND

◆ EXEC_FLAG_SKIP_TRIGGERS

#define EXEC_FLAG_SKIP_TRIGGERS   0x0010 /* skip AfterTrigger calls */

◆ EXEC_FLAG_WITH_NO_DATA

#define EXEC_FLAG_WITH_NO_DATA   0x0020 /* rel scannability doesn't matter */

Definition at line 61 of file executor.h.

Referenced by ExecOpenScanRelation(), GetIntoRelEFlags(), and InitPlan().

◆ GetPerTupleExprContext

◆ GetPerTupleMemoryContext

◆ ResetExprContext

◆ ResetPerTupleExprContext

#define ResetPerTupleExprContext (   estate)
Value:
do { \
if ((estate)->es_per_tuple_exprcontext) \
ResetExprContext((estate)->es_per_tuple_exprcontext); \
} while (0)

Definition at line 516 of file executor.h.

Referenced by comparetup_cluster(), CopyFrom(), ExecModifyTable(), ExecPostprocessPlan(), and ExecutePlan().

Typedef Documentation

◆ ExecScanAccessMtd

typedef TupleTableSlot*(* ExecScanAccessMtd) (ScanState *node)

Definition at line 430 of file executor.h.

◆ ExecScanRecheckMtd

typedef bool(* ExecScanRecheckMtd) (ScanState *node, TupleTableSlot *slot)

Definition at line 431 of file executor.h.

◆ ExecutorCheckPerms_hook_type

typedef bool(* ExecutorCheckPerms_hook_type) (List *, bool)

Definition at line 84 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 80 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 76 of file executor.h.

◆ ExecutorRun_hook_type

typedef void(* ExecutorRun_hook_type) (QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)

Definition at line 69 of file executor.h.

◆ ExecutorStart_hook_type

typedef void(* ExecutorStart_hook_type) (QueryDesc *queryDesc, int eflags)

Definition at line 65 of file executor.h.

◆ TupOutputState

Function Documentation

◆ begin_tup_output_tupdesc()

TupOutputState* begin_tup_output_tupdesc ( DestReceiver dest,
TupleDesc  tupdesc,
const TupleTableSlotOps tts_ops 
)

Definition at line 2236 of file execTuples.c.

References CMD_SELECT, generate_unaccent_rules::dest, TupOutputState::dest, MakeSingleTupleTableSlot(), palloc(), _DestReceiver::rStartup, and TupOutputState::slot.

Referenced by CreateReplicationSlot(), ExecuteCallStmt(), ExplainQuery(), IdentifySystem(), ShowAllGUCConfig(), ShowGUCConfigOption(), and StartReplication().

2239 {
2240  TupOutputState *tstate;
2241 
2242  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2243 
2244  tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2245  tstate->dest = dest;
2246 
2247  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2248 
2249  return tstate;
2250 }
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1208
TupleTableSlot * slot
Definition: executor.h:463
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:122
void * palloc(Size size)
Definition: mcxt.c:949
DestReceiver * dest
Definition: executor.h:464

◆ BuildTupleHashTable()

TupleHashTable BuildTupleHashTable ( PlanState parent,
TupleDesc  inputDesc,
int  numCols,
AttrNumber keyColIdx,
const Oid eqfuncoids,
FmgrInfo hashfunctions,
Oid collations,
long  nbuckets,
Size  additionalsize,
MemoryContext  tablecxt,
MemoryContext  tempcxt,
bool  use_variable_hash_iv 
)

Definition at line 252 of file execGrouping.c.

References BuildTupleHashTableExt().

262 {
263  return BuildTupleHashTableExt(parent,
264  inputDesc,
265  numCols, keyColIdx,
266  eqfuncoids,
267  hashfunctions,
268  collations,
269  nbuckets, additionalsize,
270  tablecxt,
271  tablecxt,
272  tempcxt,
273  use_variable_hash_iv);
274 }
TupleHashTable BuildTupleHashTableExt(PlanState *parent, TupleDesc inputDesc, int numCols, AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, long nbuckets, Size additionalsize, MemoryContext metacxt, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
Definition: execGrouping.c:154

◆ BuildTupleHashTableExt()

TupleHashTable BuildTupleHashTableExt ( PlanState parent,
TupleDesc  inputDesc,
int  numCols,
AttrNumber keyColIdx,
const Oid eqfuncoids,
FmgrInfo hashfunctions,
Oid collations,
long  nbuckets,
Size  additionalsize,
MemoryContext  metacxt,
MemoryContext  tablecxt,
MemoryContext  tempcxt,
bool  use_variable_hash_iv 
)

Definition at line 154 of file execGrouping.c.

References Assert, CreateStandaloneExprContext(), CreateTupleDescCopy(), TupleHashTableData::cur_eq_func, TupleHashTableData::entrysize, ExecBuildGroupingEqual(), TupleHashTableData::exprcontext, TupleHashTableData::hash_iv, TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), Min, murmurhash32(), TupleHashTableData::numCols, palloc(), ParallelWorkerNumber, TupleHashTableData::tab_collations, TupleHashTableData::tab_eq_func, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, TTSOpsMinimalTuple, and work_mem.

Referenced by build_hash_table(), buildSubPlanHash(), and BuildTupleHashTable().

165 {
166  TupleHashTable hashtable;
167  Size entrysize = sizeof(TupleHashEntryData) + additionalsize;
168  MemoryContext oldcontext;
169  bool allow_jit;
170 
171  Assert(nbuckets > 0);
172 
173  /* Limit initial table size request to not more than work_mem */
174  nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize));
175 
176  oldcontext = MemoryContextSwitchTo(metacxt);
177 
178  hashtable = (TupleHashTable) palloc(sizeof(TupleHashTableData));
179 
180  hashtable->numCols = numCols;
181  hashtable->keyColIdx = keyColIdx;
182  hashtable->tab_hash_funcs = hashfunctions;
183  hashtable->tab_collations = collations;
184  hashtable->tablecxt = tablecxt;
185  hashtable->tempcxt = tempcxt;
186  hashtable->entrysize = entrysize;
187  hashtable->tableslot = NULL; /* will be made on first lookup */
188  hashtable->inputslot = NULL;
189  hashtable->in_hash_funcs = NULL;
190  hashtable->cur_eq_func = NULL;
191 
192  /*
193  * If parallelism is in use, even if the master backend is performing the
194  * scan itself, we don't want to create the hashtable exactly the same way
195  * in all workers. As hashtables are iterated over in keyspace-order,
196  * doing so in all processes in the same way is likely to lead to
197  * "unbalanced" hashtables when the table size initially is
198  * underestimated.
199  */
200  if (use_variable_hash_iv)
202  else
203  hashtable->hash_iv = 0;
204 
205  hashtable->hashtab = tuplehash_create(metacxt, nbuckets, hashtable);
206 
207  /*
208  * We copy the input tuple descriptor just for safety --- we assume all
209  * input tuples will have equivalent descriptors.
210  */
213 
214  /*
215  * If the old reset interface is used (i.e. BuildTupleHashTable, rather
216  * than BuildTupleHashTableExt), allowing JIT would lead to the generated
217  * functions to a) live longer than the query b) be re-generated each time
218  * the table is being reset. Therefore prevent JIT from being used in that
219  * case, by not providing a parent node (which prevents accessing the
220  * JitContext in the EState).
221  */
222  allow_jit = metacxt != tablecxt;
223 
224  /* build comparator for all columns */
225  /* XXX: should we support non-minimal tuples for the inputslot? */
226  hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
228  numCols,
229  keyColIdx, eqfuncoids, collations,
230  allow_jit ? parent : NULL);
231 
232  /*
233  * While not pretty, it's ok to not shut down this context, but instead
234  * rely on the containing memory context being reset, as
235  * ExecBuildGroupingEqual() only builds a very simple expression calling
236  * functions (i.e. nothing that'd employ RegisterExprContextCallback()).
237  */
239 
240  MemoryContextSwitchTo(oldcontext);
241 
242  return hashtable;
243 }
ExprContext * exprcontext
Definition: execnodes.h:713
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:357
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1208
ExprState * ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, int numCols, const AttrNumber *keyColIdx, const Oid *eqfunctions, const Oid *collations, PlanState *parent)
Definition: execExpr.c:3350
TupleTableSlot * inputslot
Definition: execnodes.h:709
#define Min(x, y)
Definition: c.h:920
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
AttrNumber * keyColIdx
Definition: execnodes.h:700
ExprState * tab_eq_func
Definition: execnodes.h:702
ExprState * cur_eq_func
Definition: execnodes.h:711
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:701
FmgrInfo * in_hash_funcs
Definition: execnodes.h:710
struct TupleHashEntryData TupleHashEntryData
MemoryContext tablecxt
Definition: execnodes.h:704
struct TupleHashTableData * TupleHashTable
Definition: execnodes.h:678
int ParallelWorkerNumber
Definition: parallel.c:112
int work_mem
Definition: globals.c:121
tuplehash_hash * hashtab
Definition: execnodes.h:698
#define Assert(condition)
Definition: c.h:738
TupleTableSlot * tableslot
Definition: execnodes.h:707
size_t Size
Definition: c.h:466
void * palloc(Size size)
Definition: mcxt.c:949
MemoryContext tempcxt
Definition: execnodes.h:705
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85

◆ check_exclusion_constraint()

void check_exclusion_constraint ( Relation  heap,
Relation  index,
IndexInfo indexInfo,
ItemPointer  tupleid,
Datum values,
bool isnull,
EState estate,
bool  newIndex 
)

Definition at line 866 of file execIndexing.c.

References CEOUC_WAIT, and check_exclusion_or_unique_constraint().

Referenced by exec_rt_fetch(), IndexCheckExclusion(), and unique_key_recheck().

871 {
872  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
873  values, isnull,
874  estate, newIndex,
875  CEOUC_WAIT, false, NULL);
876 }
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool errorOK, ItemPointer conflictTid)
Definition: execIndexing.c:646
static Datum values[MAXATTR]
Definition: bootstrap.c:167

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 564 of file execReplication.c.

References CMD_DELETE, CMD_UPDATE, ereport, errcode(), errhint(), errmsg(), ERROR, GetRelationPublicationActions(), OidIsValid, PublicationActions::pubdelete, PublicationActions::pubupdate, RelationData::rd_rel, RelationGetRelationName, and RelationGetReplicaIndex().

Referenced by CheckValidResultRel(), exec_rt_fetch(), ExecSimpleRelationDelete(), ExecSimpleRelationInsert(), and ExecSimpleRelationUpdate().

565 {
566  PublicationActions *pubactions;
567 
568  /* We only need to do checks for UPDATE and DELETE. */
569  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
570  return;
571 
572  /* If relation has replica identity we are always good. */
573  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL ||
575  return;
576 
577  /*
578  * This is either UPDATE OR DELETE and there is no replica identity.
579  *
580  * Check if the table publishes UPDATES or DELETES.
581  */
582  pubactions = GetRelationPublicationActions(rel);
583  if (cmd == CMD_UPDATE && pubactions->pubupdate)
584  ereport(ERROR,
585  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
586  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
588  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
589  else if (cmd == CMD_DELETE && pubactions->pubdelete)
590  ereport(ERROR,
591  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
592  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
594  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
595 }
int errhint(const char *fmt,...)
Definition: elog.c:1071
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4715
int errcode(int sqlerrcode)
Definition: elog.c:610
Form_pg_class rd_rel
Definition: rel.h:109
#define OidIsValid(objectId)
Definition: c.h:644
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define ereport(elevel,...)
Definition: elog.h:144
struct PublicationActions * GetRelationPublicationActions(Relation relation)
Definition: relcache.c:5298
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ CheckSubscriptionRelkind()

void CheckSubscriptionRelkind ( char  relkind,
const char *  nspname,
const char *  relname 
)

Definition at line 604 of file execReplication.c.

References ereport, errcode(), errdetail(), errmsg(), and ERROR.

Referenced by AlterSubscription_refresh(), CreateSubscription(), exec_rt_fetch(), and logicalrep_rel_open().

606 {
607  /*
608  * Give a more specific error for foreign tables.
609  */
610  if (relkind == RELKIND_FOREIGN_TABLE)
611  ereport(ERROR,
612  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
613  errmsg("cannot use relation \"%s.%s\" as logical replication target",
614  nspname, relname),
615  errdetail("\"%s.%s\" is a foreign table.",
616  nspname, relname)));
617 
618  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
619  ereport(ERROR,
620  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
621  errmsg("cannot use relation \"%s.%s\" as logical replication target",
622  nspname, relname),
623  errdetail("\"%s.%s\" is not a table.",
624  nspname, relname)));
625 }
int errcode(int sqlerrcode)
Definition: elog.c:610
NameData relname
Definition: pg_class.h:38
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation 
)

Definition at line 1076 of file execMain.c.

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

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

1077 {
1078  Relation resultRel = resultRelInfo->ri_RelationDesc;
1079  TriggerDesc *trigDesc = resultRel->trigdesc;
1080  FdwRoutine *fdwroutine;
1081 
1082  switch (resultRel->rd_rel->relkind)
1083  {
1084  case RELKIND_RELATION:
1085  case RELKIND_PARTITIONED_TABLE:
1086  CheckCmdReplicaIdentity(resultRel, operation);
1087  break;
1088  case RELKIND_SEQUENCE:
1089  ereport(ERROR,
1090  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1091  errmsg("cannot change sequence \"%s\"",
1092  RelationGetRelationName(resultRel))));
1093  break;
1094  case RELKIND_TOASTVALUE:
1095  ereport(ERROR,
1096  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1097  errmsg("cannot change TOAST relation \"%s\"",
1098  RelationGetRelationName(resultRel))));
1099  break;
1100  case RELKIND_VIEW:
1101 
1102  /*
1103  * Okay only if there's a suitable INSTEAD OF trigger. Messages
1104  * here should match rewriteHandler.c's rewriteTargetView and
1105  * RewriteQuery, except that we omit errdetail because we haven't
1106  * got the information handy (and given that we really shouldn't
1107  * get here anyway, it's not worth great exertion to get).
1108  */
1109  switch (operation)
1110  {
1111  case CMD_INSERT:
1112  if (!trigDesc || !trigDesc->trig_insert_instead_row)
1113  ereport(ERROR,
1114  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1115  errmsg("cannot insert into view \"%s\"",
1116  RelationGetRelationName(resultRel)),
1117  errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
1118  break;
1119  case CMD_UPDATE:
1120  if (!trigDesc || !trigDesc->trig_update_instead_row)
1121  ereport(ERROR,
1122  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1123  errmsg("cannot update view \"%s\"",
1124  RelationGetRelationName(resultRel)),
1125  errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
1126  break;
1127  case CMD_DELETE:
1128  if (!trigDesc || !trigDesc->trig_delete_instead_row)
1129  ereport(ERROR,
1130  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1131  errmsg("cannot delete from view \"%s\"",
1132  RelationGetRelationName(resultRel)),
1133  errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
1134  break;
1135  default:
1136  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1137  break;
1138  }
1139  break;
1140  case RELKIND_MATVIEW:
1142  ereport(ERROR,
1143  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1144  errmsg("cannot change materialized view \"%s\"",
1145  RelationGetRelationName(resultRel))));
1146  break;
1147  case RELKIND_FOREIGN_TABLE:
1148  /* Okay only if the FDW supports it */
1149  fdwroutine = resultRelInfo->ri_FdwRoutine;
1150  switch (operation)
1151  {
1152  case CMD_INSERT:
1153  if (fdwroutine->ExecForeignInsert == NULL)
1154  ereport(ERROR,
1155  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1156  errmsg("cannot insert into foreign table \"%s\"",
1157  RelationGetRelationName(resultRel))));
1158  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1159  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1160  ereport(ERROR,
1161  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1162  errmsg("foreign table \"%s\" does not allow inserts",
1163  RelationGetRelationName(resultRel))));
1164  break;
1165  case CMD_UPDATE:
1166  if (fdwroutine->ExecForeignUpdate == NULL)
1167  ereport(ERROR,
1168  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1169  errmsg("cannot update foreign table \"%s\"",
1170  RelationGetRelationName(resultRel))));
1171  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1172  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1173  ereport(ERROR,
1174  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1175  errmsg("foreign table \"%s\" does not allow updates",
1176  RelationGetRelationName(resultRel))));
1177  break;
1178  case CMD_DELETE:
1179  if (fdwroutine->ExecForeignDelete == NULL)
1180  ereport(ERROR,
1181  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1182  errmsg("cannot delete from foreign table \"%s\"",
1183  RelationGetRelationName(resultRel))));
1184  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1185  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1186  ereport(ERROR,
1187  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1188  errmsg("foreign table \"%s\" does not allow deletes",
1189  RelationGetRelationName(resultRel))));
1190  break;
1191  default:
1192  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1193  break;
1194  }
1195  break;
1196  default:
1197  ereport(ERROR,
1198  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1199  errmsg("cannot change relation \"%s\"",
1200  RelationGetRelationName(resultRel))));
1201  break;
1202  }
1203 }
ExecForeignDelete_function ExecForeignDelete
Definition: fdwapi.h:213
Relation ri_RelationDesc
Definition: execnodes.h:413
int errhint(const char *fmt,...)
Definition: elog.c:1071
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition: matview.c:908
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:211
int errcode(int sqlerrcode)
Definition: elog.c:610
Form_pg_class rd_rel
Definition: rel.h:109
bool trig_insert_instead_row
Definition: reltrigger.h:58
#define ERROR
Definition: elog.h:43
TriggerDesc * trigdesc
Definition: rel.h:115
#define RelationGetRelationName(relation)
Definition: rel.h:490
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:442
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
bool trig_update_instead_row
Definition: reltrigger.h:63
bool trig_delete_instead_row
Definition: reltrigger.h:68
#define ereport(elevel,...)
Definition: elog.h:144
ExecForeignUpdate_function ExecForeignUpdate
Definition: fdwapi.h:212
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
IsForeignRelUpdatable_function IsForeignRelUpdatable
Definition: fdwapi.h:217

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 89 of file execUtils.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, EState::es_auxmodifytables, EState::es_crosscheck_snapshot, EState::es_direction, EState::es_exprcontexts, EState::es_finished, EState::es_instrument, EState::es_jit, EState::es_jit_flags, EState::es_junkFilter, EState::es_num_result_relations, EState::es_num_root_result_relations, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_per_tuple_exprcontext, EState::es_plannedstmt, EState::es_processed, EState::es_query_cxt, EState::es_queryEnv, EState::es_range_table, EState::es_range_table_size, EState::es_relations, EState::es_result_relation_info, EState::es_result_relations, EState::es_root_result_relations, EState::es_rowmarks, EState::es_snapshot, EState::es_sourceText, EState::es_subplanstates, EState::es_top_eflags, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, EState::es_tupleTable, EState::es_use_parallel_mode, ForwardScanDirection, InvalidSnapshot, makeNode, MemoryContextSwitchTo(), and NIL.

Referenced by afterTriggerInvokeEvents(), ATRewriteTable(), check_default_partition_contents(), compute_index_stats(), CopyFrom(), create_estate_for_relation(), EvalPlanQualStart(), evaluate_expr(), ExecuteCallStmt(), ExecuteQuery(), ExecuteTruncateGuts(), ExplainExecuteQuery(), get_qual_for_range(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), operator_predicate_proof(), plpgsql_create_econtext(), plpgsql_inline_handler(), standard_ExecutorStart(), StoreAttrDefault(), tuplesort_begin_cluster(), unique_key_recheck(), validateCheckConstraint(), and validateDomainConstraint().

90 {
91  EState *estate;
92  MemoryContext qcontext;
93  MemoryContext oldcontext;
94 
95  /*
96  * Create the per-query context for this Executor run.
97  */
99  "ExecutorState",
101 
102  /*
103  * Make the EState node within the per-query context. This way, we don't
104  * need a separate pfree() operation for it at shutdown.
105  */
106  oldcontext = MemoryContextSwitchTo(qcontext);
107 
108  estate = makeNode(EState);
109 
110  /*
111  * Initialize all fields of the Executor State structure
112  */
114  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
115  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
116  estate->es_range_table = NIL;
117  estate->es_range_table_size = 0;
118  estate->es_relations = NULL;
119  estate->es_rowmarks = NULL;
120  estate->es_plannedstmt = NULL;
121 
122  estate->es_junkFilter = NULL;
123 
124  estate->es_output_cid = (CommandId) 0;
125 
126  estate->es_result_relations = NULL;
127  estate->es_num_result_relations = 0;
128  estate->es_result_relation_info = NULL;
129 
130  estate->es_root_result_relations = NULL;
131  estate->es_num_root_result_relations = 0;
132 
134 
135  estate->es_trig_target_relations = NIL;
136 
137  estate->es_param_list_info = NULL;
138  estate->es_param_exec_vals = NULL;
139 
140  estate->es_queryEnv = NULL;
141 
142  estate->es_query_cxt = qcontext;
143 
144  estate->es_tupleTable = NIL;
145 
146  estate->es_processed = 0;
147 
148  estate->es_top_eflags = 0;
149  estate->es_instrument = 0;
150  estate->es_finished = false;
151 
152  estate->es_exprcontexts = NIL;
153 
154  estate->es_subplanstates = NIL;
155 
156  estate->es_auxmodifytables = NIL;
157 
158  estate->es_per_tuple_exprcontext = NULL;
159 
160  estate->es_sourceText = NULL;
161 
162  estate->es_use_parallel_mode = false;
163 
164  estate->es_jit_flags = 0;
165  estate->es_jit = NULL;
166 
167  /*
168  * Return the executor state structure
169  */
170  MemoryContextSwitchTo(oldcontext);
171 
172  return estate;
173 }
#define NIL
Definition: pg_list.h:65
uint32 CommandId
Definition: c.h:527
JunkFilter * es_junkFilter
Definition: execnodes.h:519
#define AllocSetContextCreate
Definition: memutils.h:170
CommandId es_output_cid
Definition: execnodes.h:522
struct JitContext * es_jit
Definition: execnodes.h:601
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlannedStmt * es_plannedstmt
Definition: execnodes.h:516
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:509
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:576
Snapshot es_snapshot
Definition: execnodes.h:508
List * es_range_table
Definition: execnodes.h:510
ScanDirection es_direction
Definition: execnodes.h:507
bool es_use_parallel_mode
Definition: execnodes.h:586
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:514
const char * es_sourceText
Definition: execnodes.h:517
ParamExecData * es_param_exec_vals
Definition: execnodes.h:550
MemoryContext es_query_cxt
Definition: execnodes.h:555
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
int es_jit_flags
Definition: execnodes.h:600
ResultRelInfo * es_result_relations
Definition: execnodes.h:525
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
int es_instrument
Definition: execnodes.h:562
QueryEnvironment * es_queryEnv
Definition: execnodes.h:552
int es_num_root_result_relations
Definition: execnodes.h:536
#define InvalidSnapshot
Definition: snapshot.h:123
List * es_trig_target_relations
Definition: execnodes.h:546
List * es_tupleTable
Definition: execnodes.h:557
List * es_auxmodifytables
Definition: execnodes.h:569
int es_num_result_relations
Definition: execnodes.h:526
List * es_tuple_routing_result_relations
Definition: execnodes.h:543
bool es_finished
Definition: execnodes.h:563
#define makeNode(_type_)
Definition: nodes.h:577
Relation * es_relations
Definition: execnodes.h:512
uint64 es_processed
Definition: execnodes.h:559
Index es_range_table_size
Definition: execnodes.h:511
List * es_subplanstates
Definition: execnodes.h:567
int es_top_eflags
Definition: execnodes.h:561
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:535
ParamListInfo es_param_list_info
Definition: execnodes.h:549
List * es_exprcontexts
Definition: execnodes.h:565
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:527

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 306 of file execUtils.c.

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

Referenced by ExecAssignExprContext(), ExecInitMergeJoin(), ExecInitSubPlan(), ExecuteCallStmt(), MakePerTupleExprContext(), and plpgsql_create_econtext().

307 {
309 }
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: execUtils.c:236
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 357 of file execUtils.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ExprContext::caseValue_datum, ExprContext::caseValue_isNull, CurrentMemoryContext, ExprContext::domainValue_datum, ExprContext::domainValue_isNull, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExprContext::ecxt_callbacks, ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_param_list_info, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, and makeNode.

Referenced by BuildTupleHashTableExt(), domain_check_input(), and hypothetical_dense_rank_final().

358 {
359  ExprContext *econtext;
360 
361  /* Create the ExprContext node within the caller's memory context */
362  econtext = makeNode(ExprContext);
363 
364  /* Initialize fields of ExprContext */
365  econtext->ecxt_scantuple = NULL;
366  econtext->ecxt_innertuple = NULL;
367  econtext->ecxt_outertuple = NULL;
368 
370 
371  /*
372  * Create working memory for expression evaluation in this context.
373  */
374  econtext->ecxt_per_tuple_memory =
376  "ExprContext",
378 
379  econtext->ecxt_param_exec_vals = NULL;
380  econtext->ecxt_param_list_info = NULL;
381 
382  econtext->ecxt_aggvalues = NULL;
383  econtext->ecxt_aggnulls = NULL;
384 
385  econtext->caseValue_datum = (Datum) 0;
386  econtext->caseValue_isNull = true;
387 
388  econtext->domainValue_datum = (Datum) 0;
389  econtext->domainValue_isNull = true;
390 
391  econtext->ecxt_estate = NULL;
392 
393  econtext->ecxt_callbacks = NULL;
394 
395  return econtext;
396 }
#define AllocSetContextCreate
Definition: memutils.h:170
Datum * ecxt_aggvalues
Definition: execnodes.h:245
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:234
Datum domainValue_datum
Definition: execnodes.h:257
Datum caseValue_datum
Definition: execnodes.h:251
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:265
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:228
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:237
struct EState * ecxt_estate
Definition: execnodes.h:262
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
bool domainValue_isNull
Definition: execnodes.h:259
bool * ecxt_aggnulls
Definition: execnodes.h:247
uintptr_t Datum
Definition: postgres.h:367
#define makeNode(_type_)
Definition: nodes.h:577
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:230
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
bool caseValue_isNull
Definition: execnodes.h:253
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:238

◆ CreateWorkExprContext()

ExprContext* CreateWorkExprContext ( EState estate)

Definition at line 321 of file execUtils.c.

References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, CreateExprContextInternal(), and work_mem.

Referenced by ExecInitAgg().

322 {
323  Size minContextSize = ALLOCSET_DEFAULT_MINSIZE;
324  Size initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
325  Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
326 
327  /* choose the maxBlockSize to be no larger than 1/16 of work_mem */
328  while (16 * maxBlockSize > work_mem * 1024L)
329  maxBlockSize >>= 1;
330 
331  if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
332  maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
333 
334  return CreateExprContextInternal(estate, minContextSize,
335  initBlockSize, maxBlockSize);
336 }
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: execUtils.c:236
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:189
int work_mem
Definition: globals.c:121
size_t Size
Definition: c.h:466
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:190
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:191

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 2284 of file execTuples.c.

References cstring_to_text_with_len(), DatumGetPointer, do_tup_output(), pfree(), PointerGetDatum, and values.

Referenced by ExplainQuery().

2285 {
2286  Datum values[1];
2287  bool isnull[1] = {false};
2288 
2289  while (*txt)
2290  {
2291  const char *eol;
2292  int len;
2293 
2294  eol = strchr(txt, '\n');
2295  if (eol)
2296  {
2297  len = eol - txt;
2298  eol++;
2299  }
2300  else
2301  {
2302  len = strlen(txt);
2303  eol = txt + len;
2304  }
2305 
2306  values[0] = PointerGetDatum(cstring_to_text_with_len(txt, len));
2307  do_tup_output(tstate, values, isnull);
2308  pfree(DatumGetPointer(values[0]));
2309  txt = eol;
2310  }
2311 }
#define PointerGetDatum(X)
Definition: postgres.h:556
void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
Definition: execTuples.c:2256
void pfree(void *pointer)
Definition: mcxt.c:1056
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167

◆ do_tup_output()

void do_tup_output ( TupOutputState tstate,
Datum values,
bool isnull 
)

Definition at line 2256 of file execTuples.c.

References TupOutputState::dest, ExecClearTuple(), ExecStoreVirtualTuple(), TupleDescData::natts, _DestReceiver::receiveSlot, TupOutputState::slot, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, and TupleTableSlot::tts_values.

Referenced by CreateReplicationSlot(), do_text_output_multiline(), IdentifySystem(), ShowAllGUCConfig(), and StartReplication().

2257 {
2258  TupleTableSlot *slot = tstate->slot;
2259  int natts = slot->tts_tupleDescriptor->natts;
2260 
2261  /* make sure the slot is clear */
2262  ExecClearTuple(slot);
2263 
2264  /* insert data */
2265  memcpy(slot->tts_values, values, natts * sizeof(Datum));
2266  memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2267 
2268  /* mark slot as containing a virtual tuple */
2269  ExecStoreVirtualTuple(slot);
2270 
2271  /* send the tuple to the receiver */
2272  (void) tstate->dest->receiveSlot(slot, tstate->dest);
2273 
2274  /* clean up */
2275  ExecClearTuple(slot);
2276 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:119
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
Datum * tts_values
Definition: tuptable.h:126
TupleTableSlot * slot
Definition: executor.h:463
bool * tts_isnull
Definition: tuptable.h:128
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
uintptr_t Datum
Definition: postgres.h:367
static Datum values[MAXATTR]
Definition: bootstrap.c:167
DestReceiver * dest
Definition: executor.h:464
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1522

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 2314 of file execTuples.c.

References TupOutputState::dest, ExecDropSingleTupleTableSlot(), pfree(), _DestReceiver::rShutdown, and TupOutputState::slot.

Referenced by CreateReplicationSlot(), ExecuteCallStmt(), ExplainQuery(), IdentifySystem(), ShowAllGUCConfig(), ShowGUCConfigOption(), and StartReplication().

2315 {
2316  tstate->dest->rShutdown(tstate->dest);
2317  /* note that destroying the dest is not ours to do */
2319  pfree(tstate);
2320 }
TupleTableSlot * slot
Definition: executor.h:463
void pfree(void *pointer)
Definition: mcxt.c:1056
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1224
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:125
DestReceiver * dest
Definition: executor.h:464

◆ EvalPlanQual()

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

Definition at line 2432 of file execMain.c.

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

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

2434 {
2435  TupleTableSlot *slot;
2436  TupleTableSlot *testslot;
2437 
2438  Assert(rti > 0);
2439 
2440  /*
2441  * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2442  */
2443  EvalPlanQualBegin(epqstate);
2444 
2445  /*
2446  * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
2447  * an unnecessary copy.
2448  */
2449  testslot = EvalPlanQualSlot(epqstate, relation, rti);
2450  if (testslot != inputslot)
2451  ExecCopySlot(testslot, inputslot);
2452 
2453  /*
2454  * Run the EPQ query. We assume it will return at most one tuple.
2455  */
2456  slot = EvalPlanQualNext(epqstate);
2457 
2458  /*
2459  * If we got a tuple, force the slot to materialize the tuple so that it
2460  * is not dependent on any local state in the EPQ query (in particular,
2461  * it's highly likely that the slot contains references to any pass-by-ref
2462  * datums that may be present in copyTuple). As with the next step, this
2463  * is to guard against early re-use of the EPQ query.
2464  */
2465  if (!TupIsNull(slot))
2466  ExecMaterializeSlot(slot);
2467 
2468  /*
2469  * Clear out the test tuple. This is needed in case the EPQ query is
2470  * re-used to test a tuple for a different relation. (Not clear that can
2471  * really happen, but let's be safe.)
2472  */
2473  ExecClearTuple(testslot);
2474 
2475  return slot;
2476 }
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:475
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition: execMain.c:2678
TupleTableSlot * EvalPlanQualSlot(EPQState *epqstate, Relation relation, Index rti)
Definition: execMain.c:2541
#define TupIsNull(slot)
Definition: tuptable.h:292
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:443
#define Assert(condition)
Definition: c.h:738
void EvalPlanQualBegin(EPQState *epqstate)
Definition: execMain.c:2694

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2694 of file execMain.c.

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

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

2695 {
2696  EState *parentestate = epqstate->parentestate;
2697  EState *recheckestate = epqstate->recheckestate;
2698 
2699  if (recheckestate == NULL)
2700  {
2701  /* First time through, so create a child EState */
2702  EvalPlanQualStart(epqstate, epqstate->plan);
2703  }
2704  else
2705  {
2706  /*
2707  * We already have a suitable child EPQ tree, so just reset it.
2708  */
2709  Index rtsize = parentestate->es_range_table_size;
2710  PlanState *rcplanstate = epqstate->recheckplanstate;
2711 
2712  MemSet(epqstate->relsubs_done, 0, rtsize * sizeof(bool));
2713 
2714  /* Recopy current values of parent parameters */
2715  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2716  {
2717  int i;
2718 
2719  /*
2720  * Force evaluation of any InitPlan outputs that could be needed
2721  * by the subplan, just in case they got reset since
2722  * EvalPlanQualStart (see comments therein).
2723  */
2724  ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2725  GetPerTupleExprContext(parentestate));
2726 
2727  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2728 
2729  while (--i >= 0)
2730  {
2731  /* copy value if any, but not execPlan link */
2732  recheckestate->es_param_exec_vals[i].value =
2733  parentestate->es_param_exec_vals[i].value;
2734  recheckestate->es_param_exec_vals[i].isnull =
2735  parentestate->es_param_exec_vals[i].isnull;
2736  }
2737  }
2738 
2739  /*
2740  * Mark child plan tree as needing rescan at all scan nodes. The
2741  * first ExecProcNode will take care of actually doing the rescan.
2742  */
2743  rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2744  epqstate->epqParam);
2745  }
2746 }
List * paramExecTypes
Definition: plannodes.h:90
#define NIL
Definition: pg_list.h:65
void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext)
Definition: nodeSubplan.c:1245
PlannedStmt * es_plannedstmt
Definition: execnodes.h:516
#define MemSet(start, val, len)
Definition: c.h:971
EState * parentestate
Definition: execnodes.h:1081
#define GetPerTupleExprContext(estate)
Definition: executor.h:507
ParamExecData * es_param_exec_vals
Definition: execnodes.h:550
EState * recheckestate
Definition: execnodes.h:1111
bool isnull
Definition: params.h:150
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition: execMain.c:2755
bool * relsubs_done
Definition: execnodes.h:1124
Bitmapset * chgParam
Definition: execnodes.h:977
Plan * plan
Definition: execnodes.h:1097
unsigned int Index
Definition: c.h:475
Plan * plan
Definition: execnodes.h:945
static int list_length(const List *l)
Definition: pg_list.h:169
Bitmapset * extParam
Definition: plannodes.h:160
Index es_range_table_size
Definition: execnodes.h:511
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
int i
Datum value
Definition: params.h:149
int epqParam
Definition: execnodes.h:1082
PlanState * recheckplanstate
Definition: execnodes.h:1126

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2932 of file execMain.c.

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

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

2933 {
2934  EState *estate = epqstate->recheckestate;
2935  Index rtsize;
2936  MemoryContext oldcontext;
2937  ListCell *l;
2938 
2939  rtsize = epqstate->parentestate->es_range_table_size;
2940 
2941  /*
2942  * We may have a tuple table, even if EPQ wasn't started, because we allow
2943  * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
2944  */
2945  if (epqstate->tuple_table != NIL)
2946  {
2947  memset(epqstate->relsubs_slot, 0,
2948  rtsize * sizeof(TupleTableSlot *));
2949  ExecResetTupleTable(epqstate->tuple_table, true);
2950  epqstate->tuple_table = NIL;
2951  }
2952 
2953  /* EPQ wasn't started, nothing further to do */
2954  if (estate == NULL)
2955  return;
2956 
2957  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
2958 
2959  ExecEndNode(epqstate->recheckplanstate);
2960 
2961  foreach(l, estate->es_subplanstates)
2962  {
2963  PlanState *subplanstate = (PlanState *) lfirst(l);
2964 
2965  ExecEndNode(subplanstate);
2966  }
2967 
2968  /* throw away the per-estate tuple table, some node may have used it */
2969  ExecResetTupleTable(estate->es_tupleTable, false);
2970 
2971  /* close any trigger target relations attached to this EState */
2972  ExecCleanUpTriggerState(estate);
2973 
2974  MemoryContextSwitchTo(oldcontext);
2975 
2976  FreeExecutorState(estate);
2977 
2978  /* Mark EPQState idle */
2979  epqstate->origslot = NULL;
2980  epqstate->recheckestate = NULL;
2981  epqstate->recheckplanstate = NULL;
2982  epqstate->relsubs_rowmark = NULL;
2983  epqstate->relsubs_done = NULL;
2984 }
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1090
#define NIL
Definition: pg_list.h:65
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:543
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
EState * parentestate
Definition: execnodes.h:1081
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
MemoryContext es_query_cxt
Definition: execnodes.h:555
EState * recheckestate
Definition: execnodes.h:1111
List * tuple_table
Definition: execnodes.h:1089
bool * relsubs_done
Definition: execnodes.h:1124
TupleTableSlot * origslot
Definition: execnodes.h:1106
List * es_tupleTable
Definition: execnodes.h:557
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1161
unsigned int Index
Definition: c.h:475
#define lfirst(lc)
Definition: pg_list.h:190
Index es_range_table_size
Definition: execnodes.h:511
List * es_subplanstates
Definition: execnodes.h:567
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1454
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1118
PlanState * recheckplanstate
Definition: execnodes.h:1126

◆ EvalPlanQualFetchRowMark()

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

Definition at line 2569 of file execMain.c.

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

Referenced by ExecScanFetch().

2570 {
2571  ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1];
2572  ExecRowMark *erm = earm->rowmark;
2573  Datum datum;
2574  bool isNull;
2575 
2576  Assert(earm != NULL);
2577  Assert(epqstate->origslot != NULL);
2578 
2580  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2581 
2582  /* if child rel, must check whether it produced this row */
2583  if (erm->rti != erm->prti)
2584  {
2585  Oid tableoid;
2586 
2587  datum = ExecGetJunkAttribute(epqstate->origslot,
2588  earm->toidAttNo,
2589  &isNull);
2590  /* non-locked rels could be on the inside of outer joins */
2591  if (isNull)
2592  return false;
2593 
2594  tableoid = DatumGetObjectId(datum);
2595 
2596  Assert(OidIsValid(erm->relid));
2597  if (tableoid != erm->relid)
2598  {
2599  /* this child is inactive right now */
2600  return false;
2601  }
2602  }
2603 
2604  if (erm->markType == ROW_MARK_REFERENCE)
2605  {
2606  Assert(erm->relation != NULL);
2607 
2608  /* fetch the tuple's ctid */
2609  datum = ExecGetJunkAttribute(epqstate->origslot,
2610  earm->ctidAttNo,
2611  &isNull);
2612  /* non-locked rels could be on the inside of outer joins */
2613  if (isNull)
2614  return false;
2615 
2616  /* fetch requests on foreign tables must be passed to their FDW */
2617  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2618  {
2619  FdwRoutine *fdwroutine;
2620  bool updated = false;
2621 
2622  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2623  /* this should have been checked already, but let's be safe */
2624  if (fdwroutine->RefetchForeignRow == NULL)
2625  ereport(ERROR,
2626  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2627  errmsg("cannot lock rows in foreign table \"%s\"",
2629 
2630  fdwroutine->RefetchForeignRow(epqstate->recheckestate,
2631  erm,
2632  datum,
2633  slot,
2634  &updated);
2635  if (TupIsNull(slot))
2636  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2637 
2638  /*
2639  * Ideally we'd insist on updated == false here, but that assumes
2640  * that FDWs can track that exactly, which they might not be able
2641  * to. So just ignore the flag.
2642  */
2643  return true;
2644  }
2645  else
2646  {
2647  /* ordinary table, fetch the tuple */
2649  (ItemPointer) DatumGetPointer(datum),
2650  SnapshotAny, slot))
2651  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2652  return true;
2653  }
2654  }
2655  else
2656  {
2657  Assert(erm->markType == ROW_MARK_COPY);
2658 
2659  /* fetch the whole-row Var for the relation */
2660  datum = ExecGetJunkAttribute(epqstate->origslot,
2661  earm->wholeAttNo,
2662  &isNull);
2663  /* non-locked rels could be on the inside of outer joins */
2664  if (isNull)
2665  return false;
2666 
2667  ExecStoreHeapTupleDatum(datum, slot);
2668  return true;
2669  }
2670 }
Relation relation
Definition: execnodes.h:627
#define DatumGetObjectId(X)
Definition: postgres.h:500
int errcode(int sqlerrcode)
Definition: elog.c:610
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:1033
ExecRowMark * rowmark
Definition: execnodes.h:654
#define ERROR
Definition: elog.h:43
EState * recheckestate
Definition: execnodes.h:1111
Index rti
Definition: execnodes.h:629
AttrNumber wholeAttNo
Definition: execnodes.h:657
Index prti
Definition: execnodes.h:630
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define TupIsNull(slot)
Definition: tuptable.h:292
TupleTableSlot * origslot
Definition: execnodes.h:1106
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
Definition: execTuples.c:1576
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
Definition: tableam.h:1052
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
RowMarkType markType
Definition: execnodes.h:632
AttrNumber toidAttNo
Definition: execnodes.h:656
#define SnapshotAny
Definition: snapmgr.h:69
#define DatumGetPointer(X)
Definition: postgres.h:549
int errmsg(const char *fmt,...)
Definition: elog.c:824
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:427
Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: execJunk.c:247
#define elog(elevel,...)
Definition: elog.h:214
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1118
AttrNumber ctidAttNo
Definition: execnodes.h:655
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:225

◆ EvalPlanQualInit()

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

Definition at line 2486 of file execMain.c.

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

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

2488 {
2489  Index rtsize = parentestate->es_range_table_size;
2490 
2491  /* initialize data not changing over EPQState's lifetime */
2492  epqstate->parentestate = parentestate;
2493  epqstate->epqParam = epqParam;
2494 
2495  /*
2496  * Allocate space to reference a slot for each potential rti - do so now
2497  * rather than in EvalPlanQualBegin(), as done for other dynamically
2498  * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2499  * that *may* need EPQ later, without forcing the overhead of
2500  * EvalPlanQualBegin().
2501  */
2502  epqstate->tuple_table = NIL;
2503  epqstate->relsubs_slot = (TupleTableSlot **)
2504  palloc0(rtsize * sizeof(TupleTableSlot *));
2505 
2506  /* ... and remember data that EvalPlanQualBegin will need */
2507  epqstate->plan = subplan;
2508  epqstate->arowMarks = auxrowmarks;
2509 
2510  /* ... and mark the EPQ state inactive */
2511  epqstate->origslot = NULL;
2512  epqstate->recheckestate = NULL;
2513  epqstate->recheckplanstate = NULL;
2514  epqstate->relsubs_rowmark = NULL;
2515  epqstate->relsubs_done = NULL;
2516 }
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1090
#define NIL
Definition: pg_list.h:65
EState * parentestate
Definition: execnodes.h:1081
EState * recheckestate
Definition: execnodes.h:1111
List * arowMarks
Definition: execnodes.h:1098
List * tuple_table
Definition: execnodes.h:1089
bool * relsubs_done
Definition: execnodes.h:1124
TupleTableSlot * origslot
Definition: execnodes.h:1106
Plan * plan
Definition: execnodes.h:1097
void * palloc0(Size size)
Definition: mcxt.c:980
unsigned int Index
Definition: c.h:475
Index es_range_table_size
Definition: execnodes.h:511
int epqParam
Definition: execnodes.h:1082
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1118
PlanState * recheckplanstate
Definition: execnodes.h:1126

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 2678 of file execMain.c.

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

Referenced by EvalPlanQual(), and ExecLockRows().

2679 {
2680  MemoryContext oldcontext;
2681  TupleTableSlot *slot;
2682 
2683  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2684  slot = ExecProcNode(epqstate->recheckplanstate);
2685  MemoryContextSwitchTo(oldcontext);
2686 
2687  return slot;
2688 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:555
EState * recheckestate
Definition: execnodes.h:1111
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:240
PlanState * recheckplanstate
Definition: execnodes.h:1126

◆ EvalPlanQualSetPlan()

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

Definition at line 2524 of file execMain.c.

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

Referenced by ExecInitModifyTable(), and ExecModifyTable().

2525 {
2526  /* If we have a live EPQ query, shut it down */
2527  EvalPlanQualEnd(epqstate);
2528  /* And set/change the plan pointer */
2529  epqstate->plan = subplan;
2530  /* The rowmarks depend on the plan, too */
2531  epqstate->arowMarks = auxrowmarks;
2532 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2932
List * arowMarks
Definition: execnodes.h:1098
Plan * plan
Definition: execnodes.h:1097

◆ EvalPlanQualSlot()

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

Definition at line 2541 of file execMain.c.

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

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

2543 {
2544  TupleTableSlot **slot;
2545 
2546  Assert(relation);
2547  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2548  slot = &epqstate->relsubs_slot[rti - 1];
2549 
2550  if (*slot == NULL)
2551  {
2552  MemoryContext oldcontext;
2553 
2554  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2555  *slot = table_slot_create(relation, &epqstate->tuple_table);
2556  MemoryContextSwitchTo(oldcontext);
2557  }
2558 
2559  return *slot;
2560 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:77
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1090
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
EState * parentestate
Definition: execnodes.h:1081
MemoryContext es_query_cxt
Definition: execnodes.h:555
List * tuple_table
Definition: execnodes.h:1089
#define Assert(condition)
Definition: c.h:738

◆ exec_rt_fetch()

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

Definition at line 540 of file execUtils.c.

References ExecBuildProjectionInfo(), PlanState::plan, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::ps_ResultTupleSlot, and Plan::targetlist.

Referenced by ExecConditionalAssignProjectionInfo(), ExecInitAgg(), ExecInitGroup(), ExecInitHashJoin(), ExecInitMergeJoin(), ExecInitNestLoop(), ExecInitResult(), and ExecInitWindowAgg().

542 {
543  planstate->ps_ProjInfo =
545  planstate->ps_ExprContext,
546  planstate->ps_ResultTupleSlot,
547  planstate,
548  inputDesc);
549 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:985
ExprContext * ps_ExprContext
Definition: execnodes.h:984
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:983
Plan * plan
Definition: execnodes.h:945
List * targetlist
Definition: plannodes.h:142
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:353

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
Index  varno 
)

Definition at line 285 of file execScan.c.

References ExecConditionalAssignProjectionInfo(), ScanState::ps, ScanState::ss_ScanTupleSlot, and TupleTableSlot::tts_tupleDescriptor.

Referenced by ExecInitCustomScan(), ExecInitForeignScan(), and ExecInitIndexOnlyScan().

286 {
288 
289  ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, varno);
290 }
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1335
void ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc, Index varno)
Definition: execUtils.c:560
PlanState ps
Definition: execnodes.h:1332
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 675 of file execUtils.c.

References ExecSetSlotDescriptor(), and ScanState::ss_ScanTupleSlot.

Referenced by ExecWorkTableScan().

676 {
677  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
678 
679  ExecSetSlotDescriptor(slot, tupDesc);
680 }
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1335
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:1259

◆ ExecBuildAggTrans()

ExprState* ExecBuildAggTrans ( AggState aggstate,
struct AggStatePerPhaseData phase,
bool  doSort,
bool  doHash,
bool  nullcheck 
)

Referenced by ExecProcNode().

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2362 of file execMain.c.

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

2363 {
2364  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2365  char resname[32];
2366 
2367  aerm->rowmark = erm;
2368 
2369  /* Look up the resjunk columns associated with this rowmark */
2370  if (erm->markType != ROW_MARK_COPY)
2371  {
2372  /* need ctid for all methods other than COPY */
2373  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2374  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2375  resname);
2376  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2377  elog(ERROR, "could not find junk %s column", resname);
2378  }
2379  else
2380  {
2381  /* need wholerow if COPY */
2382  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2383  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2384  resname);
2385  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2386  elog(ERROR, "could not find junk %s column", resname);
2387  }
2388 
2389  /* if child rel, need tableoid */
2390  if (erm->rti != erm->prti)
2391  {
2392  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2393  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2394  resname);
2395  if (!AttributeNumberIsValid(aerm->toidAttNo))
2396  elog(ERROR, "could not find junk %s column", resname);
2397  }
2398 
2399  return aerm;
2400 }
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:220
ExecRowMark * rowmark
Definition: execnodes.h:654
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:629
AttrNumber wholeAttNo
Definition: execnodes.h:657
Index prti
Definition: execnodes.h:630
Index rowmarkId
Definition: execnodes.h:631
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void * palloc0(Size size)
Definition: mcxt.c:980
RowMarkType markType
Definition: execnodes.h:632
AttrNumber toidAttNo
Definition: execnodes.h:656
#define elog(elevel,...)
Definition: elog.h:214
#define snprintf
Definition: port.h:193
AttrNumber ctidAttNo
Definition: execnodes.h:655

◆ ExecBuildGroupingEqual()

ExprState* ExecBuildGroupingEqual ( TupleDesc  ldesc,
TupleDesc  rdesc,
const TupleTableSlotOps lops,
const TupleTableSlotOps rops,
int  numCols,
const AttrNumber keyColIdx,
const Oid eqfunctions,
const Oid collations,
PlanState parent 
)

Definition at line 3350 of file execExpr.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert, ExprEvalStep::d, EEO_FLAG_IS_QUAL, EEOP_DONE, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, EEOP_NOT_DISTINCT, EEOP_OUTER_FETCHSOME, EEOP_OUTER_VAR, EEOP_QUAL, ExecComputeSlotInfo(), ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprEvalStep::fetch, ExprState::flags, fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_addr, ExprEvalStep::func, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvokeFunctionExecuteHook, NullableDatum::isnull, lappend_int(), lfirst_int, makeNode, NIL, OBJECT_FUNCTION, ExprEvalStep::opcode, palloc0(), ExprState::parent, pg_proc_aclcheck(), ExprEvalStep::qualexpr, ExprState::resnull, ExprEvalStep::resnull, ExprState::resvalue, ExprEvalStep::resvalue, SizeForFunctionCallInfo, ExprState::steps, ExprState::steps_len, TupleDescAttr, NullableDatum::value, and ExprEvalStep::var.

Referenced by BuildTupleHashTableExt(), ExecInitSubPlan(), ExecProcNode(), and execTuplesMatchPrepare().

3357 {
3359  ExprEvalStep scratch = {0};
3360  int maxatt = -1;
3361  List *adjust_jumps = NIL;
3362  ListCell *lc;
3363 
3364  /*
3365  * When no columns are actually compared, the result's always true. See
3366  * special case in ExecQual().
3367  */
3368  if (numCols == 0)
3369  return NULL;
3370 
3371  state->expr = NULL;
3372  state->flags = EEO_FLAG_IS_QUAL;
3373  state->parent = parent;
3374 
3375  scratch.resvalue = &state->resvalue;
3376  scratch.resnull = &state->resnull;
3377 
3378  /* compute max needed attribute */
3379  for (int natt = 0; natt < numCols; natt++)
3380  {
3381  int attno = keyColIdx[natt];
3382 
3383  if (attno > maxatt)
3384  maxatt = attno;
3385  }
3386  Assert(maxatt >= 0);
3387 
3388  /* push deform steps */
3389  scratch.opcode = EEOP_INNER_FETCHSOME;
3390  scratch.d.fetch.last_var = maxatt;
3391  scratch.d.fetch.fixed = false;
3392  scratch.d.fetch.known_desc = ldesc;
3393  scratch.d.fetch.kind = lops;
3394  if (ExecComputeSlotInfo(state, &scratch))
3395  ExprEvalPushStep(state, &scratch);
3396 
3397  scratch.opcode = EEOP_OUTER_FETCHSOME;
3398  scratch.d.fetch.last_var = maxatt;
3399  scratch.d.fetch.fixed = false;
3400  scratch.d.fetch.known_desc = rdesc;
3401  scratch.d.fetch.kind = rops;
3402  if (ExecComputeSlotInfo(state, &scratch))
3403  ExprEvalPushStep(state, &scratch);
3404 
3405  /*
3406  * Start comparing at the last field (least significant sort key). That's
3407  * the most likely to be different if we are dealing with sorted input.
3408  */
3409  for (int natt = numCols; --natt >= 0;)
3410  {
3411  int attno = keyColIdx[natt];
3412  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3413  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3414  Oid foid = eqfunctions[natt];
3415  Oid collid = collations[natt];
3416  FmgrInfo *finfo;
3417  FunctionCallInfo fcinfo;
3418  AclResult aclresult;
3419 
3420  /* Check permission to call function */
3421  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
3422  if (aclresult != ACLCHECK_OK)
3423  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3424 
3426 
3427  /* Set up the primary fmgr lookup information */
3428  finfo = palloc0(sizeof(FmgrInfo));
3429  fcinfo = palloc0(SizeForFunctionCallInfo(2));
3430  fmgr_info(foid, finfo);
3431  fmgr_info_set_expr(NULL, finfo);
3432  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3433  collid, NULL, NULL);
3434 
3435  /* left arg */
3436  scratch.opcode = EEOP_INNER_VAR;
3437  scratch.d.var.attnum = attno - 1;
3438  scratch.d.var.vartype = latt->atttypid;
3439  scratch.resvalue = &fcinfo->args[0].value;
3440  scratch.resnull = &fcinfo->args[0].isnull;
3441  ExprEvalPushStep(state, &scratch);
3442 
3443  /* right arg */
3444  scratch.opcode = EEOP_OUTER_VAR;
3445  scratch.d.var.attnum = attno - 1;
3446  scratch.d.var.vartype = ratt->atttypid;
3447  scratch.resvalue = &fcinfo->args[1].value;
3448  scratch.resnull = &fcinfo->args[1].isnull;
3449  ExprEvalPushStep(state, &scratch);
3450 
3451  /* evaluate distinctness */
3452  scratch.opcode = EEOP_NOT_DISTINCT;
3453  scratch.d.func.finfo = finfo;
3454  scratch.d.func.fcinfo_data = fcinfo;
3455  scratch.d.func.fn_addr = finfo->fn_addr;
3456  scratch.d.func.nargs = 2;
3457  scratch.resvalue = &state->resvalue;
3458  scratch.resnull = &state->resnull;
3459  ExprEvalPushStep(state, &scratch);
3460 
3461  /* then emit EEOP_QUAL to detect if result is false (or null) */
3462  scratch.opcode = EEOP_QUAL;
3463  scratch.d.qualexpr.jumpdone = -1;
3464  scratch.resvalue = &state->resvalue;
3465  scratch.resnull = &state->resnull;
3466  ExprEvalPushStep(state, &scratch);
3467  adjust_jumps = lappend_int(adjust_jumps,
3468  state->steps_len - 1);
3469  }
3470 
3471  /* adjust jump targets */
3472  foreach(lc, adjust_jumps)
3473  {
3474  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3475 
3476  Assert(as->opcode == EEOP_QUAL);
3477  Assert(as->d.qualexpr.jumpdone == -1);
3478  as->d.qualexpr.jumpdone = state->steps_len;
3479  }
3480 
3481  scratch.resvalue = NULL;
3482  scratch.resnull = NULL;
3483  scratch.opcode = EEOP_DONE;
3484  ExprEvalPushStep(state, &scratch);
3485 
3486  ExecReadyExpr(state);
3487 
3488  return state;
3489 }
#define NIL
Definition: pg_list.h:65
Definition: fmgr.h:56
struct PlanState * parent
Definition: execnodes.h:108
Datum * resvalue
Definition: execExpr.h:253
Oid GetUserId(void)
Definition: miscinit.c:448
PGFunction fn_addr
Definition: fmgr.h:58
struct ExprEvalStep * steps
Definition: execnodes.h:85
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
struct ExprEvalStep::@51::@52 fetch
bool * resnull
Definition: execExpr.h:254
unsigned int Oid
Definition: postgres_ext.h:31
struct ExprEvalStep::@51::@58 func
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3327
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:191
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1471
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Datum value
Definition: postgres.h:378
List * lappend_int(List *list, int datum)
Definition: list.c:339
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
union ExprEvalStep::@51 d
void * palloc0(Size size)
Definition: mcxt.c:980
AclResult
Definition: acl.h:177
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2372
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
struct ExprEvalStep::@51::@53 var
#define makeNode(_type_)
Definition: nodes.h:577
#define Assert(condition)
Definition: c.h:738
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
int steps_len
Definition: execnodes.h:104
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4620
uint8 flags
Definition: execnodes.h:65
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:74
struct ExprEvalStep::@51::@60 qualexpr

◆ ExecBuildProjectionInfo()

ProjectionInfo* ExecBuildProjectionInfo ( List targetList,
ExprContext econtext,
TupleTableSlot slot,
PlanState parent,
TupleDesc  inputDesc 
)

Definition at line 353 of file execExpr.c.

References ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, attnum, ExprEvalStep::d, EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_ASSIGN_TMP_MAKE_RO, EEOP_DONE, ExecInitExprRec(), ExecInitExprSlots(), ExecReadyExpr(), ExprState::expr, TargetEntry::expr, ExprEvalPushStep(), exprType(), ExprState::ext_params, get_typlen(), INNER_VAR, IsA, lfirst_node, makeNode, ExprEvalStep::opcode, OUTER_VAR, ExprState::parent, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TargetEntry::resno, ExprState::resnull, ExprState::resultslot, ExprState::resvalue, T_ExprState, ExprState::tag, TupleDescAttr, Var::varattno, Var::varno, and Var::vartype.

Referenced by ExecAssignProjectionInfo(), ExecInitModifyTable(), ExecInitPartitionInfo(), ExecInitSubPlan(), and ExecProcNode().

358 {
360  ExprState *state;
361  ExprEvalStep scratch = {0};
362  ListCell *lc;
363 
364  projInfo->pi_exprContext = econtext;
365  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
366  projInfo->pi_state.tag = T_ExprState;
367  state = &projInfo->pi_state;
368  state->expr = (Expr *) targetList;
369  state->parent = parent;
370  state->ext_params = NULL;
371 
372  state->resultslot = slot;
373 
374  /* Insert EEOP_*_FETCHSOME steps as needed */
375  ExecInitExprSlots(state, (Node *) targetList);
376 
377  /* Now compile each tlist column */
378  foreach(lc, targetList)
379  {
380  TargetEntry *tle = lfirst_node(TargetEntry, lc);
381  Var *variable = NULL;
382  AttrNumber attnum = 0;
383  bool isSafeVar = false;
384 
385  /*
386  * If tlist expression is a safe non-system Var, use the fast-path
387  * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
388  * CheckVarSlotCompatibility() during plan startup. If a source slot
389  * was provided, we make the equivalent tests here; if a slot was not
390  * provided, we assume that no check is needed because we're dealing
391  * with a non-relation-scan-level expression.
392  */
393  if (tle->expr != NULL &&
394  IsA(tle->expr, Var) &&
395  ((Var *) tle->expr)->varattno > 0)
396  {
397  /* Non-system Var, but how safe is it? */
398  variable = (Var *) tle->expr;
399  attnum = variable->varattno;
400 
401  if (inputDesc == NULL)
402  isSafeVar = true; /* can't check, just assume OK */
403  else if (attnum <= inputDesc->natts)
404  {
405  Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
406 
407  /*
408  * If user attribute is dropped or has a type mismatch, don't
409  * use ASSIGN_*_VAR. Instead let the normal expression
410  * machinery handle it (which'll possibly error out).
411  */
412  if (!attr->attisdropped && variable->vartype == attr->atttypid)
413  {
414  isSafeVar = true;
415  }
416  }
417  }
418 
419  if (isSafeVar)
420  {
421  /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
422  switch (variable->varno)
423  {
424  case INNER_VAR:
425  /* get the tuple from the inner node */
426  scratch.opcode = EEOP_ASSIGN_INNER_VAR;
427  break;
428 
429  case OUTER_VAR:
430  /* get the tuple from the outer node */
431  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
432  break;
433 
434  /* INDEX_VAR is handled by default case */
435 
436  default:
437  /* get the tuple from the relation being scanned */
438  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
439  break;
440  }
441 
442  scratch.d.assign_var.attnum = attnum - 1;
443  scratch.d.assign_var.resultnum = tle->resno - 1;
444  ExprEvalPushStep(state, &scratch);
445  }
446  else
447  {
448  /*
449  * Otherwise, compile the column expression normally.
450  *
451  * We can't tell the expression to evaluate directly into the
452  * result slot, as the result slot (and the exprstate for that
453  * matter) can change between executions. We instead evaluate
454  * into the ExprState's resvalue/resnull and then move.
455  */
456  ExecInitExprRec(tle->expr, state,
457  &state->resvalue, &state->resnull);
458 
459  /*
460  * Column might be referenced multiple times in upper nodes, so
461  * force value to R/O - but only if it could be an expanded datum.
462  */
463  if (get_typlen(exprType((Node *) tle->expr)) == -1)
465  else
466  scratch.opcode = EEOP_ASSIGN_TMP;
467  scratch.d.assign_tmp.resultnum = tle->resno - 1;
468  ExprEvalPushStep(state, &scratch);
469  }
470  }
471 
472  scratch.opcode = EEOP_DONE;
473  ExprEvalPushStep(state, &scratch);
474 
475  ExecReadyExpr(state);
476 
477  return projInfo;
478 }
NodeTag tag
Definition: execnodes.h:63
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
struct PlanState * parent
Definition: execnodes.h:108
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
ParamListInfo ext_params
Definition: execnodes.h:109
Definition: nodes.h:529
AttrNumber varattno
Definition: primnodes.h:186
struct ExprEvalStep::@51::@55 assign_var
TupleTableSlot * resultslot
Definition: execnodes.h:80
Definition: primnodes.h:181
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
Oid vartype
Definition: primnodes.h:188
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2256
#define lfirst_node(type, lc)
Definition: pg_list.h:193
AttrNumber resno
Definition: primnodes.h:1408
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
union ExprEvalStep::@51 d
Index varno
Definition: primnodes.h:184
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
int16 attnum
Definition: pg_attribute.h:79
#define INNER_VAR
Definition: primnodes.h:171
#define makeNode(_type_)
Definition: nodes.h:577
struct ExprEvalStep::@51::@56 assign_tmp
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
Expr * expr
Definition: primnodes.h:1407
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2036
ExprState pi_state
Definition: execnodes.h:333
ExprContext * pi_exprContext
Definition: execnodes.h:335
Datum resvalue
Definition: execnodes.h:74
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:172

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext context 
)

Definition at line 599 of file execExpr.c.

References Assert, DatumGetBool, EEO_FLAG_IS_QUAL, ExecEvalExprSwitchContext(), and ExprState::flags.

Referenced by ATRewriteTable(), check_default_partition_contents(), domain_check_input(), ExecPartitionCheck(), ExecQualAndReset(), ExecRelCheck(), and validateCheckConstraint().

600 {
601  Datum ret;
602  bool isnull;
603 
604  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
605  if (state == NULL)
606  return true;
607 
608  /* verify that expression was not compiled using ExecInitQual */
609  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
610 
611  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
612 
613  if (isnull)
614  return true;
615 
616  return DatumGetBool(ret);
617 }
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:305
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
#define DatumGetBool(X)
Definition: postgres.h:393
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:738
uint8 flags
Definition: execnodes.h:65

◆ ExecCheckIndexConstraints()

bool ExecCheckIndexConstraints ( TupleTableSlot slot,
EState estate,
ItemPointer  conflictTid,
List arbiterIndexes 
)

Definition at line 482 of file execIndexing.c.

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), ExprContext::ecxt_scantuple, elog, ereport, errcode(), errmsg(), ERROR, errtableconstraint(), EState::es_result_relation_info, ExecPrepareQual(), ExecQual(), FormIndexDatum(), GetPerTupleExprContext, i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, IndexInfo::ii_ReadyForInserts, IndexInfo::ii_Unique, INDEX_MAX_KEYS, ItemPointerSetInvalid, list_member_oid(), NIL, RelationData::rd_index, RelationGetRelationName, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, and values.

Referenced by exec_rt_fetch(), and ExecInsert().

485 {
486  ResultRelInfo *resultRelInfo;
487  int i;
488  int numIndices;
489  RelationPtr relationDescs;
490  Relation heapRelation;
491  IndexInfo **indexInfoArray;
492  ExprContext *econtext;
494  bool isnull[INDEX_MAX_KEYS];
495  ItemPointerData invalidItemPtr;
496  bool checkedIndex = false;
497 
498  ItemPointerSetInvalid(conflictTid);
499  ItemPointerSetInvalid(&invalidItemPtr);
500 
501  /*
502  * Get information from the result relation info structure.
503  */
504  resultRelInfo = estate->es_result_relation_info;
505  numIndices = resultRelInfo->ri_NumIndices;
506  relationDescs = resultRelInfo->ri_IndexRelationDescs;
507  indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
508  heapRelation = resultRelInfo->ri_RelationDesc;
509 
510  /*
511  * We will use the EState's per-tuple context for evaluating predicates
512  * and index expressions (creating it if it's not already there).
513  */
514  econtext = GetPerTupleExprContext(estate);
515 
516  /* Arrange for econtext's scan tuple to be the tuple under test */
517  econtext->ecxt_scantuple = slot;
518 
519  /*
520  * For each index, form index tuple and check if it satisfies the
521  * constraint.
522  */
523  for (i = 0; i < numIndices; i++)
524  {
525  Relation indexRelation = relationDescs[i];
526  IndexInfo *indexInfo;
527  bool satisfiesConstraint;
528 
529  if (indexRelation == NULL)
530  continue;
531 
532  indexInfo = indexInfoArray[i];
533 
534  if (!indexInfo->ii_Unique && !indexInfo->ii_ExclusionOps)
535  continue;
536 
537  /* If the index is marked as read-only, ignore it */
538  if (!indexInfo->ii_ReadyForInserts)
539  continue;
540 
541  /* When specific arbiter indexes requested, only examine them */
542  if (arbiterIndexes != NIL &&
543  !list_member_oid(arbiterIndexes,
544  indexRelation->rd_index->indexrelid))
545  continue;
546 
547  if (!indexRelation->rd_index->indimmediate)
548  ereport(ERROR,
549  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
550  errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),
551  errtableconstraint(heapRelation,
552  RelationGetRelationName(indexRelation))));
553 
554  checkedIndex = true;
555 
556  /* Check for partial index */
557  if (indexInfo->ii_Predicate != NIL)
558  {
559  ExprState *predicate;
560 
561  /*
562  * If predicate state not set up yet, create it (in the estate's
563  * per-query context)
564  */
565  predicate = indexInfo->ii_PredicateState;
566  if (predicate == NULL)
567  {
568  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
569  indexInfo->ii_PredicateState = predicate;
570  }
571 
572  /* Skip this index-update if the predicate isn't satisfied */
573  if (!ExecQual(predicate, econtext))
574  continue;
575  }
576 
577  /*
578  * FormIndexDatum fills in its values and isnull parameters with the
579  * appropriate values for the column(s) of the index.
580  */
581  FormIndexDatum(indexInfo,
582  slot,
583  estate,
584  values,
585  isnull);
586 
587  satisfiesConstraint =
588  check_exclusion_or_unique_constraint(heapRelation, indexRelation,
589  indexInfo, &invalidItemPtr,
590  values, isnull, estate, false,
591  CEOUC_WAIT, true,
592  conflictTid);
593  if (!satisfiesConstraint)
594  return false;
595  }
596 
597  if (arbiterIndexes != NIL && !checkedIndex)
598  elog(ERROR, "unexpected failure to find arbiter index");
599 
600  return true;
601 }
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:2595
int ri_NumIndices
Definition: execnodes.h:416
#define NIL
Definition: pg_list.h:65
Relation ri_RelationDesc
Definition: execnodes.h:413
List * ii_Predicate
Definition: execnodes.h:163
ExprState * ii_PredicateState
Definition: execnodes.h:164
int errcode(int sqlerrcode)
Definition: elog.c:610
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:370
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool errorOK, ItemPointer conflictTid)
Definition: execIndexing.c:646
#define GetPerTupleExprContext(estate)
Definition: executor.h:507
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5543
Form_pg_index rd_index
Definition: rel.h:174
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:490
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:520
bool ii_ReadyForInserts
Definition: execnodes.h:173
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
bool ii_Unique
Definition: execnodes.h:172
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
#define INDEX_MAX_KEYS
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
Oid * ii_ExclusionOps
Definition: execnodes.h:165
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:422
int i
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:419
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:527

◆ ExecCheckRTPerms()

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

Definition at line 571 of file execMain.c.

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

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

572 {
573  ListCell *l;
574  bool result = true;
575 
576  foreach(l, rangeTable)
577  {
578  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
579 
580  result = ExecCheckRTEPerms(rte);
581  if (!result)
582  {
583  Assert(rte->rtekind == RTE_RELATION);
584  if (ereport_on_violation)
586  get_rel_name(rte->relid));
587  return false;
588  }
589  }
590 
592  result = (*ExecutorCheckPerms_hook) (rangeTable,
593  ereport_on_violation);
594  return result;
595 }
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1866
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3327
static bool ExecCheckRTEPerms(RangeTblEntry *rte)
Definition: execMain.c:602
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:76
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
RTEKind rtekind
Definition: parsenodes.h:976
ObjectType get_relkind_objtype(char relkind)
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1791

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1126 of file execUtils.c.

References lfirst_node, and TargetEntry::resjunk.

Referenced by check_sql_fn_retval(), exec_rt_fetch(), and ExecTypeFromTLInternal().

1127 {
1128  int len = 0;
1129  ListCell *tl;
1130 
1131  foreach(tl, targetlist)
1132  {
1133  TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1134 
1135  if (!curTle->resjunk)
1136  len++;
1137  }
1138  return len;
1139 }
bool resjunk
Definition: primnodes.h:1414
#define lfirst_node(type, lc)
Definition: pg_list.h:193

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 1920 of file execTuples.c.

References ExecTypeFromTLInternal().

Referenced by ExecInitJunkFilter(), PlanCacheComputeResultDesc(), and PortalStart().

1921 {
1922  return ExecTypeFromTLInternal(targetList, true);
1923 }
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
Definition: execTuples.c:1926

◆ ExecCleanUpTriggerState()

void ExecCleanUpTriggerState ( EState estate)

Definition at line 1454 of file execMain.c.

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

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

1455 {
1456  ListCell *l;
1457 
1458  foreach(l, estate->es_trig_target_relations)
1459  {
1460  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1461 
1462  /*
1463  * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
1464  * might be issuing a duplicate close against a Relation opened by
1465  * ExecGetRangeTableRelation.
1466  */
1467  Assert(resultRelInfo->ri_RangeTableIndex == 0);
1468 
1469  /*
1470  * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
1471  * these rels, we needn't call ExecCloseIndices either.
1472  */
1473  Assert(resultRelInfo->ri_NumIndices == 0);
1474 
1475  table_close(resultRelInfo->ri_RelationDesc, NoLock);
1476  }
1477 }
int ri_NumIndices
Definition: execnodes.h:416
Relation ri_RelationDesc
Definition: execnodes.h:413
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Index ri_RangeTableIndex
Definition: execnodes.h:410
#define NoLock
Definition: lockdefs.h:34
List * es_trig_target_relations
Definition: execnodes.h:546
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 226 of file execIndexing.c.

References i, index_close(), ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_NumIndices, and RowExclusiveLock.

Referenced by apply_handle_delete_internal(), apply_handle_insert_internal(), apply_handle_tuple_routing(), apply_handle_update_internal(), CatalogCloseIndexes(), CopyFrom(), exec_rt_fetch(), ExecCleanupTupleRouting(), and ExecEndPlan().

227 {
228  int i;
229  int numIndices;
230  RelationPtr indexDescs;
231 
232  numIndices = resultRelInfo->ri_NumIndices;
233  indexDescs = resultRelInfo->ri_IndexRelationDescs;
234 
235  for (i = 0; i < numIndices; i++)
236  {
237  if (indexDescs[i] == NULL)
238  continue; /* shouldn't happen? */
239 
240  /* Drop lock acquired by ExecOpenIndices */
241  index_close(indexDescs[i], RowExclusiveLock);
242  }
243 
244  /*
245  * XXX should free indexInfo array here too? Currently we assume that
246  * such stuff will be cleaned up automatically in FreeExecutorState.
247  */
248 }
int ri_NumIndices
Definition: execnodes.h:416
#define RowExclusiveLock
Definition: lockdefs.h:38
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
int i
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:419

◆ ExecConditionalAssignProjectionInfo()

void ExecConditionalAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc,
Index  varno 
)

Definition at line 560 of file execUtils.c.

References ExecAssignProjectionInfo(), ExecInitResultSlot(), PlanState::plan, PlanState::ps_ProjInfo, PlanState::ps_ResultTupleSlot, PlanState::resultops, PlanState::resultopsfixed, PlanState::resultopsset, PlanState::scanops, PlanState::scanopsfixed, PlanState::scanopsset, Plan::targetlist, tlist_matches_tupdesc(), and TTSOpsVirtual.

Referenced by ExecAssignScanProjectionInfo(), ExecAssignScanProjectionInfoWithVarno(), ExecInitGather(), and ExecInitGatherMerge().

562 {
563  if (tlist_matches_tupdesc(planstate,
564  planstate->plan->targetlist,
565  varno,
566  inputDesc))
567  {
568  planstate->ps_ProjInfo = NULL;
569  planstate->resultopsset = planstate->scanopsset;
570  planstate->resultopsfixed = planstate->scanopsfixed;
571  planstate->resultops = planstate->scanops;
572  }
573  else
574  {
575  if (!planstate->ps_ResultTupleSlot)
576  {
577  ExecInitResultSlot(planstate, &TTSOpsVirtual);
578  planstate->resultops = &TTSOpsVirtual;
579  planstate->resultopsfixed = true;
580  planstate->resultopsset = true;
581  }
582  ExecAssignProjectionInfo(planstate, inputDesc);
583  }
584 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:985
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
const TupleTableSlotOps * resultops
Definition: execnodes.h:1020
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:983
const TupleTableSlotOps * scanops
Definition: execnodes.h:1017
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:540
bool resultopsset
Definition: execnodes.h:1028
Plan * plan
Definition: execnodes.h:945
bool scanopsfixed
Definition: execnodes.h:1021
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1749
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
Definition: execUtils.c:587
bool scanopsset
Definition: execnodes.h:1025
List * targetlist
Definition: plannodes.h:142
bool resultopsfixed
Definition: execnodes.h:1024

◆ ExecConstraints()

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

Definition at line 1897 of file execMain.c.

References Assert, bms_union(), build_attrmap_by_name_if_req(), TupleDescData::constr, ereport, errcode(), errdetail(), errmsg(), ERROR, errtablecol(), errtableconstraint(), ExecBuildSlotValueDescription(), ExecRelCheck(), execute_attr_map_slot(), GetInsertedColumns, GetUpdatedColumns, TupleConstr::has_not_null, MakeTupleTableSlot(), NameStr, TupleDescData::natts, TupleConstr::num_check, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ResultRelInfo::ri_PartitionCheck, ResultRelInfo::ri_PartitionRoot, ResultRelInfo::ri_RelationDesc, slot_attisnull(), TTSOpsVirtual, and TupleDescAttr.

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

1899 {
1900  Relation rel = resultRelInfo->ri_RelationDesc;
1901  TupleDesc tupdesc = RelationGetDescr(rel);
1902  TupleConstr *constr = tupdesc->constr;
1903  Bitmapset *modifiedCols;
1904  Bitmapset *insertedCols;
1905  Bitmapset *updatedCols;
1906 
1907  Assert(constr || resultRelInfo->ri_PartitionCheck);
1908 
1909  if (constr && constr->has_not_null)
1910  {
1911  int natts = tupdesc->natts;
1912  int attrChk;
1913 
1914  for (attrChk = 1; attrChk <= natts; attrChk++)
1915  {
1916  Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
1917 
1918  if (att->attnotnull && slot_attisnull(slot, attrChk))
1919  {
1920  char *val_desc;
1921  Relation orig_rel = rel;
1922  TupleDesc orig_tupdesc = RelationGetDescr(rel);
1923 
1924  /*
1925  * If the tuple has been routed, it's been converted to the
1926  * partition's rowtype, which might differ from the root
1927  * table's. We must convert it back to the root table's
1928  * rowtype so that val_desc shown error message matches the
1929  * input tuple.
1930  */
1931  if (resultRelInfo->ri_PartitionRoot)
1932  {
1933  AttrMap *map;
1934 
1935  rel = resultRelInfo->ri_PartitionRoot;
1936  tupdesc = RelationGetDescr(rel);
1937  /* a reverse map */
1938  map = build_attrmap_by_name_if_req(orig_tupdesc,
1939  tupdesc);
1940 
1941  /*
1942  * Partition-specific slot's tupdesc can't be changed, so
1943  * allocate a new one.
1944  */
1945  if (map != NULL)
1946  slot = execute_attr_map_slot(map, slot,
1947  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
1948  }
1949 
1950  insertedCols = GetInsertedColumns(resultRelInfo, estate);
1951  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
1952  modifiedCols = bms_union(insertedCols, updatedCols);
1954  slot,
1955  tupdesc,
1956  modifiedCols,
1957  64);
1958 
1959  ereport(ERROR,
1960  (errcode(ERRCODE_NOT_NULL_VIOLATION),
1961  errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint",
1962  NameStr(att->attname),
1963  RelationGetRelationName(orig_rel)),
1964  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1965  errtablecol(orig_rel, attrChk)));
1966  }
1967  }
1968  }
1969 
1970  if (constr && constr->num_check > 0)
1971  {
1972  const char *failed;
1973 
1974  if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
1975  {
1976  char *val_desc;
1977  Relation orig_rel = rel;
1978 
1979  /* See the comment above. */
1980  if (resultRelInfo->ri_PartitionRoot)
1981  {
1982  TupleDesc old_tupdesc = RelationGetDescr(rel);
1983  AttrMap *map;
1984 
1985  rel = resultRelInfo->ri_PartitionRoot;
1986  tupdesc = RelationGetDescr(rel);
1987  /* a reverse map */
1988  map = build_attrmap_by_name_if_req(old_tupdesc,
1989  tupdesc);
1990 
1991  /*
1992  * Partition-specific slot's tupdesc can't be changed, so
1993  * allocate a new one.
1994  */
1995  if (map != NULL)
1996  slot = execute_attr_map_slot(map, slot,
1997  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
1998  }
1999 
2000  insertedCols = GetInsertedColumns(resultRelInfo, estate);
2001  updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2002  modifiedCols = bms_union(insertedCols, updatedCols);
2004  slot,
2005  tupdesc,
2006  modifiedCols,
2007  64);
2008  ereport(ERROR,
2009  (errcode(ERRCODE_CHECK_VIOLATION),
2010  errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2011  RelationGetRelationName(orig_rel), failed),
2012  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2013  errtableconstraint(orig_rel, failed)));
2014  }
2015  }
2016 }
#define GetUpdatedColumns(relinfo, estate)
Definition: execMain.c:111
Relation ri_RelationDesc
Definition: execnodes.h:413
#define RelationGetDescr(relation)
Definition: rel.h:482
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Relation ri_PartitionRoot
Definition: execnodes.h:487
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
int errcode(int sqlerrcode)
Definition: elog.c:610
Definition: attmap.h:34
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5543
AttrMap * build_attrmap_by_name_if_req(TupleDesc indesc, TupleDesc outdesc)
Definition: attmap.c:259
#define ERROR
Definition: elog.h:43
static char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2176
TupleConstr * constr
Definition: tupdesc.h:85
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define RelationGetRelationName(relation)
Definition: rel.h:490
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
List * ri_PartitionCheck
Definition: execnodes.h:481
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1082
uint16 num_check
Definition: tupdesc.h:43
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1717
#define ereport(elevel,...)
Definition: elog.h:144
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:177
#define Assert(condition)
Definition: c.h:738
int errtablecol(Relation rel, int attnum)
Definition: relcache.c:5506
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:225
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define NameStr(name)
Definition: c.h:615
bool has_not_null
Definition: tupdesc.h:44
static bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: tuptable.h:367
#define RelationGetRelid(relation)
Definition: rel.h:456
#define GetInsertedColumns(relinfo, estate)
Definition: execMain.c:109

◆ ExecCreateScanSlotFromOuterPlan()

void ExecCreateScanSlotFromOuterPlan ( EState estate,
ScanState scanstate,
const TupleTableSlotOps tts_ops 
)

Definition at line 687 of file execUtils.c.

References ExecGetResultType(), ExecInitScanTupleSlot(), outerPlan, and outerPlanState.

Referenced by ExecInitAgg(), ExecInitGroup(), ExecInitIncrementalSort(), ExecInitMaterial(), ExecInitSort(), and ExecInitWindowAgg().

690 {
692  TupleDesc tupDesc;
693 
694  outerPlan = outerPlanState(scanstate);
695  tupDesc = ExecGetResultType(outerPlan);
696 
697  ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
698 }
#define outerPlanState(node)
Definition: execnodes.h:1039
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1781
#define outerPlan(node)
Definition: plannodes.h:172
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:495

◆ execCurrentOf()

bool execCurrentOf ( CurrentOfExpr cexpr,
ExprContext econtext,
Oid  table_oid,
ItemPointer  current_tid 
)

Definition at line 44 of file execCurrent.c.

References Assert, PortalData::atEnd, PortalData::atStart, ExecRowMark::curCtid, CurrentOfExpr::cursor_name, CurrentOfExpr::cursor_param, DatumGetObjectId, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, EState::es_range_table_size, EState::es_rowmarks, QueryDesc::estate, fetch_cursor_param_value(), get_rel_name(), GetPortalByName(), i, IsA, ItemPointerIsValid, ExecRowMark::markType, QueryDesc::planstate, PORTAL_ONE_SELECT, PortalIsValid, PortalData::queryDesc, ExecRowMark::relid, RowMarkRequiresRowShareLock, search_plan_tree(), SelfItemPointerAttributeNumber, slot_getsysattr(), ScanState::ss_ScanTupleSlot, PortalData::strategy, TableOidAttributeNumber, TupIsNull, and IndexScanDescData::xs_heaptid.

Referenced by TidListEval().

48 {
49  char *cursor_name;
50  char *table_name;
51  Portal portal;
52  QueryDesc *queryDesc;
53 
54  /* Get the cursor name --- may have to look up a parameter reference */
55  if (cexpr->cursor_name)
56  cursor_name = cexpr->cursor_name;
57  else
58  cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param);
59 
60  /* Fetch table name for possible use in error messages */
61  table_name = get_rel_name(table_oid);
62  if (table_name == NULL)
63  elog(ERROR, "cache lookup failed for relation %u", table_oid);
64 
65  /* Find the cursor's portal */
66  portal = GetPortalByName(cursor_name);
67  if (!PortalIsValid(portal))
68  ereport(ERROR,
69  (errcode(ERRCODE_UNDEFINED_CURSOR),
70  errmsg("cursor \"%s\" does not exist", cursor_name)));
71 
72  /*
73  * We have to watch out for non-SELECT queries as well as held cursors,
74  * both of which may have null queryDesc.
75  */
76  if (portal->strategy != PORTAL_ONE_SELECT)
77  ereport(ERROR,
78  (errcode(ERRCODE_INVALID_CURSOR_STATE),
79  errmsg("cursor \"%s\" is not a SELECT query",
80  cursor_name)));
81  queryDesc = portal->queryDesc;
82  if (queryDesc == NULL || queryDesc->estate == NULL)
83  ereport(ERROR,
84  (errcode(ERRCODE_INVALID_CURSOR_STATE),
85  errmsg("cursor \"%s\" is held from a previous transaction",
86  cursor_name)));
87 
88  /*
89  * We have two different strategies depending on whether the cursor uses
90  * FOR UPDATE/SHARE or not. The reason for supporting both is that the
91  * FOR UPDATE code is able to identify a target table in many cases where
92  * the other code can't, while the non-FOR-UPDATE case allows use of WHERE
93  * CURRENT OF with an insensitive cursor.
94  */
95  if (queryDesc->estate->es_rowmarks)
96  {
97  ExecRowMark *erm;
98  Index i;
99 
100  /*
101  * Here, the query must have exactly one FOR UPDATE/SHARE reference to
102  * the target table, and we dig the ctid info out of that.
103  */
104  erm = NULL;
105  for (i = 0; i < queryDesc->estate->es_range_table_size; i++)
106  {
107  ExecRowMark *thiserm = queryDesc->estate->es_rowmarks[i];
108 
109  if (thiserm == NULL ||
111  continue; /* ignore non-FOR UPDATE/SHARE items */
112 
113  if (thiserm->relid == table_oid)
114  {
115  if (erm)
116  ereport(ERROR,
117  (errcode(ERRCODE_INVALID_CURSOR_STATE),
118  errmsg("cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\"",
119  cursor_name, table_name)));
120  erm = thiserm;
121  }
122  }
123 
124  if (erm == NULL)
125  ereport(ERROR,
126  (errcode(ERRCODE_INVALID_CURSOR_STATE),
127  errmsg("cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\"",
128  cursor_name, table_name)));
129 
130  /*
131  * The cursor must have a current result row: per the SQL spec, it's
132  * an error if not.
133  */
134  if (portal->atStart || portal->atEnd)
135  ereport(ERROR,
136  (errcode(ERRCODE_INVALID_CURSOR_STATE),
137  errmsg("cursor \"%s\" is not positioned on a row",
138  cursor_name)));
139 
140  /* Return the currently scanned TID, if there is one */
141  if (ItemPointerIsValid(&(erm->curCtid)))
142  {
143  *current_tid = erm->curCtid;
144  return true;
145  }
146 
147  /*
148  * This table didn't produce the cursor's current row; some other
149  * inheritance child of the same parent must have. Signal caller to
150  * do nothing on this table.
151  */
152  return false;
153  }
154  else
155  {
156  /*
157  * Without FOR UPDATE, we dig through the cursor's plan to find the
158  * scan node. Fail if it's not there or buried underneath
159  * aggregation.
160  */
161  ScanState *scanstate;
162  bool pending_rescan = false;
163 
164  scanstate = search_plan_tree(queryDesc->planstate, table_oid,
165  &pending_rescan);
166  if (!scanstate)
167  ereport(ERROR,
168  (errcode(ERRCODE_INVALID_CURSOR_STATE),
169  errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
170  cursor_name, table_name)));
171 
172  /*
173  * The cursor must have a current result row: per the SQL spec, it's
174  * an error if not. We test this at the top level, rather than at the
175  * scan node level, because in inheritance cases any one table scan
176  * could easily not be on a row. We want to return false, not raise
177  * error, if the passed-in table OID is for one of the inactive scans.
178  */
179  if (portal->atStart || portal->atEnd)
180  ereport(ERROR,
181  (errcode(ERRCODE_INVALID_CURSOR_STATE),
182  errmsg("cursor \"%s\" is not positioned on a row",
183  cursor_name)));
184 
185  /*
186  * Now OK to return false if we found an inactive scan. It is
187  * inactive either if it's not positioned on a row, or there's a
188  * rescan pending for it.
189  */
190  if (TupIsNull(scanstate->ss_ScanTupleSlot) || pending_rescan)
191  return false;
192 
193  /*
194  * Extract TID of the scan's current row. The mechanism for this is
195  * in principle scan-type-dependent, but for most scan types, we can
196  * just dig the TID out of the physical scan tuple.
197  */
198  if (IsA(scanstate, IndexOnlyScanState))
199  {
200  /*
201  * For IndexOnlyScan, the tuple stored in ss_ScanTupleSlot may be
202  * a virtual tuple that does not have the ctid column, so we have
203  * to get the TID from xs_ctup.t_self.
204  */
205  IndexScanDesc scan = ((IndexOnlyScanState *) scanstate)->ioss_ScanDesc;
206 
207  *current_tid = scan->xs_heaptid;
208  }
209  else
210  {
211  /*
212  * Default case: try to fetch TID from the scan node's current
213  * tuple. As an extra cross-check, verify tableoid in the current
214  * tuple. If the scan hasn't provided a physical tuple, we have
215  * to fail.
216  */
217  Datum ldatum;
218  bool lisnull;
219  ItemPointer tuple_tid;
220 
221 #ifdef USE_ASSERT_CHECKING
222  ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
224  &lisnull);
225  if (lisnull)
226  ereport(ERROR,
227  (errcode(ERRCODE_INVALID_CURSOR_STATE),
228  errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
229  cursor_name, table_name)));
230  Assert(DatumGetObjectId(ldatum) == table_oid);
231 #endif
232 
233  ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
235  &lisnull);
236  if (lisnull)
237  ereport(ERROR,
238  (errcode(ERRCODE_INVALID_CURSOR_STATE),
239  errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
240  cursor_name, table_name)));
241  tuple_tid = (ItemPointer) DatumGetPointer(ldatum);
242 
243  *current_tid = *tuple_tid;
244  }
245 
246  Assert(ItemPointerIsValid(current_tid));
247 
248  return true;
249  }
250 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
static ScanState * search_plan_tree(PlanState *node, Oid table_oid, bool *pending_rescan)
Definition: execCurrent.c:310
bool atEnd
Definition: portal.h:191
EState * estate
Definition: execdesc.h:48
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
#define DatumGetObjectId(X)
Definition: postgres.h:500
int errcode(int sqlerrcode)
Definition: elog.c:610
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1335
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:1033
ItemPointerData * ItemPointer
Definition: itemptr.h:49
ItemPointerData curCtid
Definition: execnodes.h:636
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:514
#define ERROR
Definition: elog.h:43
PlanState * planstate
Definition: execdesc.h:49
ItemPointerData xs_heaptid
Definition: relscan.h:132
#define TupIsNull(slot)
Definition: tuptable.h:292
#define TableOidAttributeNumber
Definition: sysattr.h:26
char * cursor_name
Definition: primnodes.h:1317
PortalStrategy strategy
Definition: portal.h:145
QueryDesc * queryDesc
Definition: portal.h:156
#define PortalIsValid(p)
Definition: portal.h:203
uintptr_t Datum
Definition: postgres.h:367
unsigned int Index
Definition: c.h:475
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
RowMarkType markType
Definition: execnodes.h:632
Index es_range_table_size
Definition: execnodes.h:511
#define DatumGetPointer(X)
Definition: postgres.h:549
bool atStart
Definition: portal.h:190
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
int i
static char * fetch_cursor_param_value(ExprContext *econtext, int paramId)
Definition: execCurrent.c:258
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:402
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1791

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 543 of file execProcnode.c.

References bms_free(), check_stack_depth(), PlanState::chgParam, elog, ERROR, ExecEndAgg(), ExecEndAppend(), ExecEndBitmapAnd(), ExecEndBitmapHeapScan(), ExecEndBitmapIndexScan(), ExecEndBitmapOr(), ExecEndCteScan(), ExecEndCustomScan(), ExecEndForeignScan(), ExecEndFunctionScan(), ExecEndGather(), ExecEndGatherMerge(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndIncrementalSort(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNamedTuplestoreScan(), ExecEndNestLoop(), ExecEndProjectSet(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSampleScan(), ExecEndSeqScan(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndTableFuncScan(), ExecEndTidScan(), ExecEndUnique(), ExecEndValuesScan(), ExecEndWindowAgg(), ExecEndWorkTableScan(), nodeTag, T_AggState, T_AppendState, T_BitmapAndState, T_BitmapHeapScanState, T_BitmapIndexScanState, T_BitmapOrState, T_CteScanState, T_CustomScanState, T_ForeignScanState, T_FunctionScanState, T_GatherMergeState, T_GatherState, T_GroupState, T_HashJoinState, T_HashState, T_IncrementalSortState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NamedTuplestoreScanState, T_NestLoopState, T_ProjectSetState, T_RecursiveUnionState, T_ResultState, T_SampleScanState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TableFuncScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, and T_WorkTableScanState.

Referenced by EvalPlanQualEnd(), ExecEndAgg(), ExecEndAppend(), ExecEndBitmapAnd(), ExecEndBitmapHeapScan(), ExecEndBitmapOr(), ExecEndForeignScan(), ExecEndGather(), ExecEndGatherMerge(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndIncrementalSort(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndPlan(), ExecEndProjectSet(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndUnique(), and ExecEndWindowAgg().

544 {
545  /*
546  * do nothing when we get to the end of a leaf on tree.
547  */
548  if (node == NULL)
549  return;
550 
551  /*
552  * Make sure there's enough stack available. Need to check here, in
553  * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
554  * guaranteed that ExecProcNode() is reached for all nodes.
555  */
557 
558  if (node->chgParam != NULL)
559  {
560  bms_free(node->chgParam);
561  node->chgParam = NULL;
562  }
563 
564  switch (nodeTag(node))
565  {
566  /*
567  * control nodes
568  */
569  case T_ResultState:
570  ExecEndResult((ResultState *) node);
571  break;
572 
573  case T_ProjectSetState:
575  break;
576 
577  case T_ModifyTableState:
579  break;
580 
581  case T_AppendState:
582  ExecEndAppend((AppendState *) node);
583  break;
584 
585  case T_MergeAppendState:
587  break;
588 
591  break;
592 
593  case T_BitmapAndState:
595  break;
596 
597  case T_BitmapOrState:
598  ExecEndBitmapOr((BitmapOrState *) node);
599  break;
600 
601  /*
602  * scan nodes
603  */
604  case T_SeqScanState:
605  ExecEndSeqScan((SeqScanState *) node);
606  break;
607 
608  case T_SampleScanState:
610  break;
611 
612  case T_GatherState:
613  ExecEndGather((GatherState *) node);
614  break;
615 
616  case T_GatherMergeState:
618  break;
619 
620  case T_IndexScanState:
622  break;
623 
626  break;
627 
630  break;
631 
634  break;
635 
636  case T_TidScanState:
637  ExecEndTidScan((TidScanState *) node);
638  break;
639 
640  case T_SubqueryScanState:
642  break;
643 
644  case T_FunctionScanState:
646  break;
647 
650  break;
651 
652  case T_ValuesScanState:
654  break;
655 
656  case T_CteScanState:
657  ExecEndCteScan((CteScanState *) node);
658  break;
659 
662  break;
663 
666  break;
667 
668  case T_ForeignScanState:
670  break;
671 
672  case T_CustomScanState:
674  break;
675 
676  /*
677  * join nodes
678  */
679  case T_NestLoopState:
680  ExecEndNestLoop((NestLoopState *) node);
681  break;
682 
683  case T_MergeJoinState:
685  break;
686 
687  case T_HashJoinState:
688  ExecEndHashJoin((HashJoinState *) node);
689  break;
690 
691  /*
692  * materialization nodes
693  */
694  case T_MaterialState:
695  ExecEndMaterial((MaterialState *) node);
696  break;
697 
698  case T_SortState:
699  ExecEndSort((SortState *) node);
700  break;
701 
704  break;
705 
706  case T_GroupState:
707  ExecEndGroup((GroupState *) node);
708  break;
709 
710  case T_AggState:
711  ExecEndAgg((AggState *) node);
712  break;
713 
714  case T_WindowAggState:
716  break;
717 
718  case T_UniqueState:
719  ExecEndUnique((UniqueState *) node);
720  break;
721 
722  case T_HashState:
723  ExecEndHash((HashState *) node);
724  break;
725 
726  case T_SetOpState:
727  ExecEndSetOp((SetOpState *) node);
728  break;
729 
730  case T_LockRowsState:
731  ExecEndLockRows((LockRowsState *) node);
732  break;
733 
734  case T_LimitState:
735  ExecEndLimit((LimitState *) node);
736  break;
737 
738  default:
739  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
740  break;
741  }
742 }
void ExecEndGroup(GroupState *node)
Definition: nodeGroup.c:227
void ExecEndSetOp(SetOpState *node)
Definition: nodeSetOp.c:583
void ExecEndFunctionScan(FunctionScanState *node)
void ExecEndNestLoop(NestLoopState *node)
Definition: nodeNestloop.c:362
void ExecEndIndexScan(IndexScanState *node)
void ExecEndLimit(LimitState *node)
Definition: nodeLimit.c:535
void ExecEndUnique(UniqueState *node)
Definition: nodeUnique.c:169
void ExecEndGatherMerge(GatherMergeState *node)
void ExecEndIncrementalSort(IncrementalSortState *node)
void ExecEndWorkTableScan(WorkTableScanState *node)
void ExecEndLockRows(LockRowsState *node)
Definition: nodeLockRows.c:382
void ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
void ExecEndBitmapAnd(BitmapAndState *node)
void ExecEndRecursiveUnion(RecursiveUnionState *node)
void ExecEndSubqueryScan(SubqueryScanState *node)
void ExecEndHashJoin(HashJoinState *node)
Definition: nodeHashjoin.c:765
void ExecEndTableFuncScan(TableFuncScanState *node)
void ExecEndResult(ResultState *node)
Definition: nodeResult.c:241
#define ERROR
Definition: elog.h:43
void ExecEndAppend(AppendState *node)
Definition: nodeAppend.c:294
void ExecEndForeignScan(ForeignScanState *node)
void ExecEndSort(SortState *node)
Definition: nodeSort.c:235
void ExecEndBitmapIndexScan(BitmapIndexScanState *node)
void check_stack_depth(void)
Definition: postgres.c:3312
void ExecEndValuesScan(ValuesScanState *node)
void ExecEndMergeJoin(MergeJoinState *node)
void ExecEndSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:184
void ExecEndIndexOnlyScan(IndexOnlyScanState *node)
void ExecEndTidScan(TidScanState *node)
Definition: nodeTidscan.c:468
Bitmapset * chgParam
Definition: execnodes.h:977
void ExecEndCteScan(CteScanState *node)
Definition: nodeCtescan.c:288
void ExecEndCustomScan(CustomScanState *node)
Definition: nodeCustom.c:119
void ExecEndBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:196
void ExecEndSampleScan(SampleScanState *node)
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
void ExecEndWindowAgg(WindowAggState *node)
void ExecEndMergeAppend(MergeAppendState *node)
#define nodeTag(nodeptr)
Definition: nodes.h:534
#define elog(elevel,...)
Definition: elog.h:214
void ExecEndHash(HashState *node)
Definition: nodeHash.c:406
void ExecEndProjectSet(ProjectSetState *node)
void ExecEndMaterial(MaterialState *node)
Definition: nodeMaterial.c:240
void ExecEndBitmapHeapScan(BitmapHeapScanState *node)
void ExecEndAgg(AggState *node)
Definition: nodeAgg.c:4483
void ExecEndModifyTable(ModifyTableState *node)
void ExecEndGather(GatherState *node)
Definition: nodeGather.c:249

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

static Datum ExecEvalExprSwitchContext ( ExprState state,
ExprContext econtext,
bool isNull 
)
inlinestatic

Definition at line 305 of file executor.h.

References ExprContext::ecxt_per_tuple_memory, ExprState::evalfunc, and MemoryContextSwitchTo().

Referenced by advance_aggregates(), evaluate_expr(), EvaluateParams(), ExecCheck(), ExecProject(), ExecQual(), ExecScanSubPlan(), ExecSetParamPlan(), ExecuteCallStmt(), ExecWindowAgg(), FormIndexDatum(), FormPartitionKeyDatum(), get_qual_for_range(), operator_predicate_proof(), partkey_datum_from_expr(), recompute_limits(), tablesample_init(), TidListEval(), and validateDomainConstraint().

308 {
309  Datum retDatum;
310  MemoryContext oldContext;
311 
312  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
313  retDatum = state->evalfunc(state, econtext, isNull);
314  MemoryContextSwitchTo(oldContext);
315  return retDatum;
316 }
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:234
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprStateEvalFunc evalfunc
Definition: execnodes.h:91
uintptr_t Datum
Definition: postgres.h:367

◆ ExecFilterJunk()

TupleTableSlot* ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 261 of file execJunk.c.

References ExecClearTuple(), ExecStoreVirtualTuple(), i, JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, TupleDescData::natts, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, and values.

Referenced by ExecBRUpdateTriggers(), ExecEvalWholeRowVar(), ExecModifyTable(), ExecUpdate(), ExecutePlan(), and sqlfunction_receive().

262 {
263  TupleTableSlot *resultSlot;
264  AttrNumber *cleanMap;
265  TupleDesc cleanTupType;
266  int cleanLength;
267  int i;
268  Datum *values;
269  bool *isnull;
270  Datum *old_values;
271  bool *old_isnull;
272 
273  /*
274  * Extract all the values of the old tuple.
275  */
276  slot_getallattrs(slot);
277  old_values = slot->tts_values;
278  old_isnull = slot->tts_isnull;
279 
280  /*
281  * get info from the junk filter
282  */
283  cleanTupType = junkfilter->jf_cleanTupType;
284  cleanLength = cleanTupType->natts;
285  cleanMap = junkfilter->jf_cleanMap;
286  resultSlot = junkfilter->jf_resultSlot;
287 
288  /*
289  * Prepare to build a virtual result tuple.
290  */
291  ExecClearTuple(resultSlot);
292  values = resultSlot->tts_values;
293  isnull = resultSlot->tts_isnull;
294 
295  /*
296  * Transpose data into proper fields of the new tuple.
297  */
298  for (i = 0; i < cleanLength; i++)
299  {
300  int j = cleanMap[i];
301 
302  if (j == 0)
303  {
304  values[i] = (Datum) 0;
305  isnull[i] = true;
306  }
307  else
308  {
309  values[i] = old_values[j - 1];
310  isnull[i] = old_isnull[j - 1];
311  }
312  }
313 
314  /*
315  * And return the virtual tuple.
316  */
317  return ExecStoreVirtualTuple(resultSlot);
318 }
AttrNumber * jf_cleanMap
Definition: execnodes.h:371
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
TupleTableSlot * jf_resultSlot
Definition: execnodes.h:372
Datum * tts_values
Definition: tuptable.h:126
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:354
bool * tts_isnull
Definition: tuptable.h:128
TupleDesc jf_cleanTupType
Definition: execnodes.h:370
uintptr_t Datum
Definition: postgres.h:367
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
int16 AttrNumber
Definition: attnum.h:21
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1522

◆ ExecFindJunkAttribute()

AttrNumber ExecFindJunkAttribute ( JunkFilter junkfilter,
const char *  attrName 
)

Definition at line 208 of file execJunk.c.

References ExecFindJunkAttributeInTlist(), and JunkFilter::jf_targetList.

Referenced by ExecInitModifyTable().

209 {
210  return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
211 }
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:220
List * jf_targetList
Definition: execnodes.h:369

◆ ExecFindJunkAttributeInTlist()

AttrNumber ExecFindJunkAttributeInTlist ( List targetlist,
const char *  attrName 
)

Definition at line 220 of file execJunk.c.

References InvalidAttrNumber, lfirst, TargetEntry::resjunk, TargetEntry::resname, and TargetEntry::resno.

Referenced by create_foreign_modify(), ExecBuildAuxRowMark(), and ExecFindJunkAttribute().

221 {
222  ListCell *t;
223 
224  foreach(t, targetlist)
225  {
226  TargetEntry *tle = lfirst(t);
227 
228  if (tle->resjunk && tle->resname &&
229  (strcmp(tle->resname, attrName) == 0))
230  {
231  /* We found it ! */
232  return tle->resno;
233  }
234  }
235 
236  return InvalidAttrNumber;
237 }
char * resname
Definition: primnodes.h:1409
bool resjunk
Definition: primnodes.h:1414
AttrNumber resno
Definition: primnodes.h:1408
#define lfirst(lc)
Definition: pg_list.h:190
#define InvalidAttrNumber
Definition: attnum.h:23

◆ ExecFindRowMark()

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

Definition at line 2339 of file execMain.c.

References elog, ERROR, and EState::es_rowmarks.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

2340 {
2341  if (rti > 0 && rti <= estate->es_range_table_size &&
2342  estate->es_rowmarks != NULL)
2343  {
2344  ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2345 
2346  if (erm)
2347  return erm;
2348  }
2349  if (!missing_ok)
2350  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2351  return NULL;
2352 }
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:514
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:214

◆ ExecFreeExprContext()

◆ ExecGetJunkAttribute()

Datum ExecGetJunkAttribute ( TupleTableSlot slot,
AttrNumber  attno,
bool isNull 
)

Definition at line 247 of file execJunk.c.

References Assert, and slot_getattr().

Referenced by EvalPlanQualFetchRowMark(), ExecLockRows(), ExecModifyTable(), and execute_foreign_modify().

249 {
250  Assert(attno > 0);
251 
252  return slot_getattr(slot, attno, isNull);
253 }
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:381
#define Assert(condition)
Definition: c.h:738

◆ ExecGetRangeTableRelation()

Relation ExecGetRangeTableRelation ( EState estate,
Index  rti 
)

Definition at line 795 of file execUtils.c.

References AccessShareLock, Assert, CheckRelationLockedByMe(), EState::es_relations, exec_rt_fetch(), IsParallelWorker, NoLock, RangeTblEntry::relid, RangeTblEntry::rellockmode, RTE_RELATION, RangeTblEntry::rtekind, and table_open().

Referenced by exec_rt_fetch(), ExecCreatePartitionPruneState(), ExecOpenScanRelation(), and InitPlan().

796 {
797  Relation rel;
798 
799  Assert(rti > 0 && rti <= estate->es_range_table_size);
800 
801  rel = estate->es_relations[rti - 1];
802  if (rel == NULL)
803  {
804  /* First time through, so open the relation */
805  RangeTblEntry *rte = exec_rt_fetch(rti, estate);
806 
807  Assert(rte->rtekind == RTE_RELATION);
808 
809  if (!IsParallelWorker())
810  {
811  /*
812  * In a normal query, we should already have the appropriate lock,
813  * but verify that through an Assert. Since there's already an
814  * Assert inside table_open that insists on holding some lock, it
815  * seems sufficient to check this only when rellockmode is higher
816  * than the minimum.
817  */
818  rel = table_open(rte->relid, NoLock);
820  CheckRelationLockedByMe(rel, rte->rellockmode, false));
821  }
822  else
823  {
824  /*
825  * If we are a parallel worker, we need to obtain our own local
826  * lock on the relation. This ensures sane behavior in case the
827  * parent process exits before we do.
828  */
829  rel = table_open(rte->relid, rte->rellockmode);
830  }
831 
832  estate->es_relations[rti - 1] = rel;
833  }
834 
835  return rel;
836 }
#define AccessShareLock
Definition: lockdefs.h:36
#define NoLock
Definition: lockdefs.h:34
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:543
#define IsParallelWorker()
Definition: parallel.h:61
#define Assert(condition)
Definition: c.h:738
Relation * es_relations
Definition: execnodes.h:512
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition: lmgr.c:302
RTEKind rtekind
Definition: parsenodes.h:976
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ ExecGetResultSlotOps()

const TupleTableSlotOps* ExecGetResultSlotOps ( PlanState planstate,
bool isfixed 
)

Definition at line 504 of file execUtils.c.

References PlanState::ps_ResultTupleSlot, PlanState::resultops, PlanState::resultopsfixed, PlanState::resultopsset, TTS_FIXED, TupleTableSlot::tts_ops, and TTSOpsVirtual.

Referenced by ExecComputeSlotInfo(), ExecInitAgg(), ExecInitGroup(), ExecInitHashJoin(), ExecInitLimit(), ExecInitLockRows(), ExecInitMergeJoin(), and ExecInitSubqueryScan().

505 {
506  if (planstate->resultopsset && planstate->resultops)
507  {
508  if (isfixed)
509  *isfixed = planstate->resultopsfixed;
510  return planstate->resultops;
511  }
512 
513  if (isfixed)
514  {
515  if (planstate->resultopsset)
516  *isfixed = planstate->resultopsfixed;
517  else if (planstate->ps_ResultTupleSlot)
518  *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
519  else
520  *isfixed = false;
521  }
522 
523  if (!planstate->ps_ResultTupleSlot)
524  return &TTSOpsVirtual;
525 
526  return planstate->ps_ResultTupleSlot->tts_ops;
527 }
#define TTS_FIXED(slot)
Definition: tuptable.h:109
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
const TupleTableSlotOps *const tts_ops
Definition: tuptable.h:122
const TupleTableSlotOps * resultops
Definition: execnodes.h:1020
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:983
bool resultopsset
Definition: execnodes.h:1028
bool resultopsfixed
Definition: execnodes.h:1024

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot* ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1189 of file execUtils.c.

References EState::es_query_cxt, ExecInitExtraTupleSlot(), MemoryContextSwitchTo(), RelationGetDescr, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_ReturningSlot, and table_slot_callbacks().

Referenced by apply_returning_filter(), exec_rt_fetch(), ExecDelete(), and ExecInsert().

1190 {
1191  if (relInfo->ri_ReturningSlot == NULL)
1192  {
1193  Relation rel = relInfo->ri_RelationDesc;
1194  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1195 
1196  relInfo->ri_ReturningSlot =
1197  ExecInitExtraTupleSlot(estate,
1198  RelationGetDescr(rel),
1199  table_slot_callbacks(rel));
1200 
1201  MemoryContextSwitchTo(oldcontext);
1202  }
1203 
1204  return relInfo->ri_ReturningSlot;
1205 }
Relation ri_RelationDesc
Definition: execnodes.h:413
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1801
#define RelationGetDescr(relation)
Definition: rel.h:482
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:44
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:555
TupleTableSlot * ri_ReturningSlot
Definition: execnodes.h:437

◆ ExecGetTriggerNewSlot()

TupleTableSlot* ExecGetTriggerNewSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1167 of file execUtils.c.

References EState::es_query_cxt, ExecInitExtraTupleSlot(), MemoryContextSwitchTo(), RelationGetDescr, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigNewSlot, and table_slot_callbacks().

Referenced by AfterTriggerExecute(), and exec_rt_fetch().

1168 {
1169  if (relInfo->ri_TrigNewSlot == NULL)
1170  {
1171  Relation rel = relInfo->ri_RelationDesc;
1172  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1173 
1174  relInfo->ri_TrigNewSlot =
1175  ExecInitExtraTupleSlot(estate,
1176  RelationGetDescr(rel),
1177  table_slot_callbacks(rel));
1178 
1179  MemoryContextSwitchTo(oldcontext);
1180  }
1181 
1182  return relInfo->ri_TrigNewSlot;
1183 }
Relation ri_RelationDesc
Definition: execnodes.h:413
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1801
#define RelationGetDescr(relation)
Definition: rel.h:482
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:44
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
TupleTableSlot * ri_TrigNewSlot
Definition: execnodes.h:439
MemoryContext es_query_cxt
Definition: execnodes.h:555

◆ ExecGetTriggerOldSlot()

TupleTableSlot* ExecGetTriggerOldSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1145 of file execUtils.c.

References EState::es_query_cxt, ExecInitExtraTupleSlot(), MemoryContextSwitchTo(), RelationGetDescr, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigOldSlot, and table_slot_callbacks().

Referenced by AfterTriggerExecute(), exec_rt_fetch(), ExecARDeleteTriggers(), ExecARUpdateTriggers(), ExecBRDeleteTriggers(), ExecBRUpdateTriggers(), ExecIRDeleteTriggers(), and ExecIRUpdateTriggers().

1146 {
1147  if (relInfo->ri_TrigOldSlot == NULL)
1148  {
1149  Relation rel = relInfo->ri_RelationDesc;
1150  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1151 
1152  relInfo->ri_TrigOldSlot =
1153  ExecInitExtraTupleSlot(estate,
1154  RelationGetDescr(rel),
1155  table_slot_callbacks(rel));
1156 
1157  MemoryContextSwitchTo(oldcontext);
1158  }
1159 
1160  return relInfo->ri_TrigOldSlot;
1161 }
Relation ri_RelationDesc
Definition: execnodes.h:413
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1801
#define RelationGetDescr(relation)
Definition: rel.h:482
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:44
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:555
TupleTableSlot * ri_TrigOldSlot
Definition: execnodes.h:438

◆ ExecGetTriggerResultRel()

ResultRelInfo* ExecGetTriggerResultRel ( EState estate,
Oid  relid 
)

Definition at line 1371 of file execMain.c.

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

Referenced by afterTriggerInvokeEvents().

1372 {
1373  ResultRelInfo *rInfo;
1374  int nr;
1375  ListCell *l;
1376  Relation rel;
1377  MemoryContext oldcontext;
1378 
1379  /* First, search through the query result relations */
1380  rInfo = estate->es_result_relations;
1381  nr = estate->es_num_result_relations;
1382  while (nr > 0)
1383  {
1384  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1385  return rInfo;
1386  rInfo++;
1387  nr--;
1388  }
1389  /* Second, search through the root result relations, if any */
1390  rInfo = estate->es_root_result_relations;
1391  nr = estate->es_num_root_result_relations;
1392  while (nr > 0)
1393  {
1394  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1395  return rInfo;
1396  rInfo++;
1397  nr--;
1398  }
1399 
1400  /*
1401  * Third, search through the result relations that were created during
1402  * tuple routing, if any.
1403  */
1404  foreach(l, estate->es_tuple_routing_result_relations)
1405  {
1406  rInfo = (ResultRelInfo *) lfirst(l);
1407  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1408  return rInfo;
1409  }
1410 
1411  /* Nope, but maybe we already made an extra ResultRelInfo for it */
1412  foreach(l, estate->es_trig_target_relations)
1413  {
1414  rInfo = (ResultRelInfo *) lfirst(l);
1415  if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1416  return rInfo;
1417  }
1418  /* Nope, so we need a new one */
1419 
1420  /*
1421  * Open the target relation's relcache entry. We assume that an
1422  * appropriate lock is still held by the backend from whenever the trigger
1423  * event got queued, so we need take no new lock here. Also, we need not
1424  * recheck the relkind, so no need for CheckValidResultRel.
1425  */
1426  rel = table_open(relid, NoLock);
1427 
1428  /*
1429  * Make the new entry in the right context.
1430  */
1431  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1432  rInfo = makeNode(ResultRelInfo);
1433  InitResultRelInfo(rInfo,
1434  rel,
1435  0, /* dummy rangetable index */
1436  NULL,
1437  estate->es_instrument);
1438  estate->es_trig_target_relations =
1439  lappend(estate->es_trig_target_relations, rInfo);
1440  MemoryContextSwitchTo(oldcontext);
1441 
1442  /*
1443  * Currently, we don't need any index information in ResultRelInfos used
1444  * only for triggers, so no need to call ExecOpenIndices.
1445  */
1446 
1447  return rInfo;
1448 }
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1277
Relation ri_RelationDesc
Definition: execnodes.h:413
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:555
#define NoLock
Definition: lockdefs.h:34
ResultRelInfo * es_result_relations
Definition: execnodes.h:525
int es_instrument
Definition: execnodes.h:562
List * lappend(List *list, void *datum)
Definition: list.c:321
int es_num_root_result_relations
Definition: execnodes.h:536
List * es_trig_target_relations
Definition: execnodes.h:546
int es_num_result_relations
Definition: execnodes.h:526
List * es_tuple_routing_result_relations
Definition: execnodes.h:543
#define makeNode(_type_)
Definition: nodes.h:577
#define lfirst(lc)
Definition: pg_list.h:190
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:535
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ ExecInitCheck()

ExprState* ExecInitCheck ( List qual,
PlanState parent 
)

Definition at line 298 of file execExpr.c.

References Assert, ExecInitExpr(), IsA, make_ands_explicit(), and NIL.

Referenced by ExecPrepareCheck(), and ExecProcNode().

299 {
300  /* short-circuit (here and in ExecCheck) for empty restriction list */
301  if (qual == NIL)
302  return NULL;
303 
304  Assert(IsA(qual, List));
305 
306  /*
307  * Just convert the implicit-AND list to an explicit AND (if there's more
308  * than one entry), and compile normally. Unlike ExecQual, we can't
309  * short-circuit on NULL results, so the regular AND behavior is needed.
310  */
311  return ExecInitExpr(make_ands_explicit(qual), parent);
312 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Expr * make_ands_explicit(List *andclauses)
Definition: makefuncs.c:705
#define Assert(condition)
Definition: c.h:738
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
Definition: pg_list.h:50

◆ ExecInitExpr()