PostgreSQL Source Code  git master
executor.h File Reference
#include "executor/execdesc.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_OIDS   0x0020 /* force OIDs in returned tuples */
 
#define EXEC_FLAG_WITHOUT_OIDS   0x0040 /* force no OIDs in returned tuples */
 
#define EXEC_FLAG_WITH_NO_DATA   0x0080 /* 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, AttrNumber *keyColIdx, Oid *eqOperators, PlanState *parent)
 
void execTuplesHashPrepare (int numCols, Oid *eqOperators, Oid **eqFuncOids, FmgrInfo **hashFunctions)
 
TupleHashTable BuildTupleHashTable (PlanState *parent, TupleDesc inputDesc, int numCols, AttrNumber *keyColIdx, Oid *eqfuncoids, FmgrInfo *hashfunctions, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
 
TupleHashEntry LookupTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
 
TupleHashEntry FindTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, ExprState *eqcomp, FmgrInfo *hashfunctions)
 
JunkFilterExecInitJunkFilter (List *targetList, bool hasoid, 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)
 
bool ExecContextForcesOids (PlanState *planstate, bool *hasoids)
 
void ExecConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool check_partition_constraint)
 
bool ExecPartitionCheck (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
 
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 (EState *estate, EPQState *epqstate, Relation relation, Index rti, int lockmode, ItemPointer tid, TransactionId priorXmax)
 
HeapTuple EvalPlanQualFetch (EState *estate, Relation relation, int lockmode, LockWaitPolicy wait_policy, ItemPointer tid, TransactionId priorXmax)
 
void EvalPlanQualInit (EPQState *epqstate, EState *estate, Plan *subplan, List *auxrowmarks, int epqParam)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
void EvalPlanQualSetTuple (EPQState *epqstate, Index rti, HeapTuple tuple)
 
HeapTuple EvalPlanQualGetTuple (EPQState *epqstate, Index rti)
 
void EvalPlanQualFetchRowMarks (EPQState *epqstate)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate, EState *parentestate)
 
void EvalPlanQualEnd (EPQState *epqstate)
 
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)
 
ExprStateExecBuildGroupingEqual (TupleDesc ldesc, TupleDesc rdesc, int numCols, AttrNumber *keyColIdx, Oid *eqfunctions, 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 ExecInitResultTupleSlotTL (EState *estate, PlanState *planstate)
 
void ExecInitScanTupleSlot (EState *estate, ScanState *scanstate, TupleDesc tupleDesc)
 
TupleTableSlotExecInitExtraTupleSlot (EState *estate, TupleDesc tupleDesc)
 
TupleTableSlotExecInitNullTupleSlot (EState *estate, TupleDesc tupType)
 
TupleDesc ExecTypeFromTL (List *targetList, bool hasoid)
 
TupleDesc ExecCleanTypeFromTL (List *targetList, bool hasoid)
 
TupleDesc ExecTypeFromExprList (List *exprList)
 
void ExecTypeSetColNames (TupleDesc typeInfo, List *namesList)
 
void UpdateChangedParamSet (PlanState *node, Bitmapset *newchg)
 
TupOutputStatebegin_tup_output_tupdesc (DestReceiver *dest, TupleDesc tupdesc)
 
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)
 
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)
 
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)
 
bool ExecRelationIsTargetRelation (EState *estate, Index scanrelid)
 
Relation ExecOpenScanRelation (EState *estate, Index scanrelid, int eflags)
 
void ExecCloseScanRelation (Relation scanrel)
 
int executor_errposition (EState *estate, int location)
 
void RegisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
void UnregisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
void ExecLockNonLeafAppendTables (List *partitioned_rels, EState *estate)
 
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)
 
void ExecOpenIndices (ResultRelInfo *resultRelInfo, bool speculative)
 
void ExecCloseIndices (ResultRelInfo *resultRelInfo)
 
ListExecInsertIndexTuples (TupleTableSlot *slot, ItemPointer tupleid, 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:541
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define DatumGetPointer(X)
Definition: postgres.h:534

Definition at line 462 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   0x0080 /* rel scannability doesn't matter */

Definition at line 65 of file executor.h.

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

◆ EXEC_FLAG_WITH_OIDS

#define EXEC_FLAG_WITH_OIDS   0x0020 /* force OIDs in returned tuples */

Definition at line 63 of file executor.h.

Referenced by ExecContextForcesOids(), and GetIntoRelEFlags().

◆ EXEC_FLAG_WITHOUT_OIDS

#define EXEC_FLAG_WITHOUT_OIDS   0x0040 /* force no OIDs in returned tuples */

Definition at line 64 of file executor.h.

Referenced by ExecContextForcesOids(), GetIntoRelEFlags(), and refresh_matview_datafill().

◆ 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 498 of file executor.h.

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 421 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 422 of file executor.h.

◆ ExecutorCheckPerms_hook_type

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

Definition at line 88 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 84 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 80 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 73 of file executor.h.

◆ ExecutorStart_hook_type

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

Definition at line 69 of file executor.h.

◆ TupOutputState

Function Documentation

◆ begin_tup_output_tupdesc()

TupOutputState* begin_tup_output_tupdesc ( DestReceiver dest,
TupleDesc  tupdesc 
)

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

1316 {
1317  TupOutputState *tstate;
1318 
1319  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
1320 
1321  tstate->slot = MakeSingleTupleTableSlot(tupdesc);
1322  tstate->dest = dest;
1323 
1324  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
1325 
1326  return tstate;
1327 }
TupleTableSlot * slot
Definition: executor.h:447
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:232
void * palloc(Size size)
Definition: mcxt.c:924
DestReceiver * dest
Definition: executor.h:448

◆ BuildTupleHashTable()

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

Definition at line 152 of file execGrouping.c.

References Assert, CreateExprContext(), CreateTupleDescCopy(), TupleHashTableData::cur_eq_func, TupleHashTableData::entrysize, ExecBuildGroupingEqual(), TupleHashTableData::exprcontext, TupleHashTableData::hash_iv, TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, MakeSingleTupleTableSlot(), MemoryContextAlloc(), MemoryContextSwitchTo(), Min, murmurhash32(), TupleHashTableData::numCols, ParallelWorkerNumber, PlanState::state, TupleHashTableData::tab_eq_func, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and work_mem.

Referenced by build_hash_table(), and buildSubPlanHash().

160 {
161  TupleHashTable hashtable;
162  Size entrysize = sizeof(TupleHashEntryData) + additionalsize;
163  MemoryContext oldcontext;
164 
165  Assert(nbuckets > 0);
166 
167  /* Limit initial table size request to not more than work_mem */
168  nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize));
169 
170  hashtable = (TupleHashTable)
171  MemoryContextAlloc(tablecxt, sizeof(TupleHashTableData));
172 
173  hashtable->numCols = numCols;
174  hashtable->keyColIdx = keyColIdx;
175  hashtable->tab_hash_funcs = hashfunctions;
176  hashtable->tablecxt = tablecxt;
177  hashtable->tempcxt = tempcxt;
178  hashtable->entrysize = entrysize;
179  hashtable->tableslot = NULL; /* will be made on first lookup */
180  hashtable->inputslot = NULL;
181  hashtable->in_hash_funcs = NULL;
182  hashtable->cur_eq_func = NULL;
183 
184  /*
185  * If parallelism is in use, even if the master backend is performing the
186  * scan itself, we don't want to create the hashtable exactly the same way
187  * in all workers. As hashtables are iterated over in keyspace-order,
188  * doing so in all processes in the same way is likely to lead to
189  * "unbalanced" hashtables when the table size initially is
190  * underestimated.
191  */
192  if (use_variable_hash_iv)
194  else
195  hashtable->hash_iv = 0;
196 
197  hashtable->hashtab = tuplehash_create(tablecxt, nbuckets, hashtable);
198 
199  oldcontext = MemoryContextSwitchTo(hashtable->tablecxt);
200 
201  /*
202  * We copy the input tuple descriptor just for safety --- we assume all
203  * input tuples will have equivalent descriptors.
204  */
205  hashtable->tableslot = MakeSingleTupleTableSlot(CreateTupleDescCopy(inputDesc));
206 
207  /* build comparator for all columns */
208  hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
209  numCols,
210  keyColIdx, eqfuncoids,
211  parent);
212 
213  MemoryContextSwitchTo(oldcontext);
214 
215  hashtable->exprcontext = CreateExprContext(parent->state);
216 
217  return hashtable;
218 }
ExprContext * exprcontext
Definition: execnodes.h:681
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
ExprState * ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, int numCols, AttrNumber *keyColIdx, Oid *eqfunctions, PlanState *parent)
Definition: execExpr.c:3216
TupleTableSlot * inputslot
Definition: execnodes.h:677
#define Min(x, y)
Definition: c.h:857
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
AttrNumber * keyColIdx
Definition: execnodes.h:669
ExprState * tab_eq_func
Definition: execnodes.h:671
ExprState * cur_eq_func
Definition: execnodes.h:679
EState * state
Definition: execnodes.h:914
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:670
FmgrInfo * in_hash_funcs
Definition: execnodes.h:678
struct TupleHashEntryData TupleHashEntryData
MemoryContext tablecxt
Definition: execnodes.h:672
struct TupleHashTableData * TupleHashTable
Definition: execnodes.h:647
int ParallelWorkerNumber
Definition: parallel.c:103
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:232
int work_mem
Definition: globals.c:122
tuplehash_hash * hashtab
Definition: execnodes.h:667
#define Assert(condition)
Definition: c.h:699
TupleTableSlot * tableslot
Definition: execnodes.h:675
size_t Size
Definition: c.h:433
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:228
static uint32 murmurhash32(uint32 data)
Definition: hashutils.h:41
MemoryContext tempcxt
Definition: execnodes.h:673

◆ 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 863 of file execIndexing.c.

References CEOUC_WAIT, and check_exclusion_or_unique_constraint().

Referenced by IndexCheckExclusion(), and unique_key_recheck().

868 {
869  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
870  values, isnull,
871  estate, newIndex,
872  CEOUC_WAIT, false, NULL);
873 }
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:639
static Datum values[MAXATTR]
Definition: bootstrap.c:164

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 552 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(), ExecSimpleRelationDelete(), ExecSimpleRelationInsert(), and ExecSimpleRelationUpdate().

553 {
554  PublicationActions *pubactions;
555 
556  /* We only need to do checks for UPDATE and DELETE. */
557  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
558  return;
559 
560  /* If relation has replica identity we are always good. */
561  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL ||
563  return;
564 
565  /*
566  * This is either UPDATE OR DELETE and there is no replica identity.
567  *
568  * Check if the table publishes UPDATES or DELETES.
569  */
570  pubactions = GetRelationPublicationActions(rel);
571  if (cmd == CMD_UPDATE && pubactions->pubupdate)
572  ereport(ERROR,
573  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
574  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
576  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
577  else if (cmd == CMD_DELETE && pubactions->pubdelete)
578  ereport(ERROR,
579  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
580  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
582  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
583 }
int errhint(const char *fmt,...)
Definition: elog.c:987
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4521
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:84
#define OidIsValid(objectId)
Definition: c.h:605
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define ereport(elevel, rest)
Definition: elog.h:122
struct PublicationActions * GetRelationPublicationActions(Relation relation)
Definition: relcache.c:5121
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ CheckSubscriptionRelkind()

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

Definition at line 592 of file execReplication.c.

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

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

594 {
595  /*
596  * We currently only support writing to regular tables.
597  */
598  if (relkind != RELKIND_RELATION)
599  ereport(ERROR,
600  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
601  errmsg("logical replication target relation \"%s.%s\" is not a table",
602  nspname, relname)));
603 }
int errcode(int sqlerrcode)
Definition: elog.c:575
char relkind
Definition: pg_class.h:51
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation 
)

Definition at line 1104 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(), ExecInitModifyTable(), ExecInitPartitionInfo(), and ExecPrepareTupleRouting().

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

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 80 of file execUtils.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, EState::es_auxmodifytables, EState::es_crosscheck_snapshot, EState::es_direction, EState::es_epqScanDone, EState::es_epqTuple, EState::es_epqTupleSet, EState::es_exprcontexts, EState::es_finished, EState::es_instrument, EState::es_jit, EState::es_jit_flags, EState::es_junkFilter, EState::es_lastoid, 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_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_newtup_slot, EState::es_trig_oldtup_slot, EState::es_trig_target_relations, EState::es_trig_tuple_slot, EState::es_tuple_routing_result_relations, EState::es_tupleTable, EState::es_use_parallel_mode, ForwardScanDirection, InvalidOid, InvalidSnapshot, makeNode, MemoryContextSwitchTo(), and NIL.

Referenced by afterTriggerInvokeEvents(), ATRewriteTable(), check_default_allows_bound(), compute_index_stats(), CopyFrom(), create_estate_for_relation(), EvalPlanQualStart(), evaluate_expr(), ExecuteCallStmt(), ExecuteQuery(), ExecuteTruncateGuts(), ExplainExecuteQuery(), get_actual_variable_range(), get_qual_for_range(), IndexBuildHeapRangeScan(), IndexCheckExclusion(), operator_predicate_proof(), plpgsql_create_econtext(), plpgsql_inline_handler(), ProjIndexIsUnchanged(), standard_ExecutorStart(), StoreAttrDefault(), tuplesort_begin_cluster(), unique_key_recheck(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().

81 {
82  EState *estate;
83  MemoryContext qcontext;
84  MemoryContext oldcontext;
85 
86  /*
87  * Create the per-query context for this Executor run.
88  */
90  "ExecutorState",
92 
93  /*
94  * Make the EState node within the per-query context. This way, we don't
95  * need a separate pfree() operation for it at shutdown.
96  */
97  oldcontext = MemoryContextSwitchTo(qcontext);
98 
99  estate = makeNode(EState);
100 
101  /*
102  * Initialize all fields of the Executor State structure
103  */
105  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
106  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
107  estate->es_range_table = NIL;
108  estate->es_plannedstmt = NULL;
109 
110  estate->es_junkFilter = NULL;
111 
112  estate->es_output_cid = (CommandId) 0;
113 
114  estate->es_result_relations = NULL;
115  estate->es_num_result_relations = 0;
116  estate->es_result_relation_info = NULL;
117 
118  estate->es_root_result_relations = NULL;
119  estate->es_num_root_result_relations = 0;
120 
122 
123  estate->es_trig_target_relations = NIL;
124  estate->es_trig_tuple_slot = NULL;
125  estate->es_trig_oldtup_slot = NULL;
126  estate->es_trig_newtup_slot = NULL;
127 
128  estate->es_param_list_info = NULL;
129  estate->es_param_exec_vals = NULL;
130 
131  estate->es_queryEnv = NULL;
132 
133  estate->es_query_cxt = qcontext;
134 
135  estate->es_tupleTable = NIL;
136 
137  estate->es_rowMarks = NIL;
138 
139  estate->es_processed = 0;
140  estate->es_lastoid = InvalidOid;
141 
142  estate->es_top_eflags = 0;
143  estate->es_instrument = 0;
144  estate->es_finished = false;
145 
146  estate->es_exprcontexts = NIL;
147 
148  estate->es_subplanstates = NIL;
149 
150  estate->es_auxmodifytables = NIL;
151 
152  estate->es_per_tuple_exprcontext = NULL;
153 
154  estate->es_epqTuple = NULL;
155  estate->es_epqTupleSet = NULL;
156  estate->es_epqScanDone = NULL;
157  estate->es_sourceText = NULL;
158 
159  estate->es_use_parallel_mode = false;
160 
161  estate->es_jit_flags = 0;
162  estate->es_jit = NULL;
163 
164  /*
165  * Return the executor state structure
166  */
167  MemoryContextSwitchTo(oldcontext);
168 
169  return estate;
170 }
#define NIL
Definition: pg_list.h:69
uint32 CommandId
Definition: c.h:488
HeapTuple * es_epqTuple
Definition: execnodes.h:558
JunkFilter * es_junkFilter
Definition: execnodes.h:484
CommandId es_output_cid
Definition: execnodes.h:487
struct JitContext * es_jit
Definition: execnodes.h:573
TupleTableSlot * es_trig_newtup_slot
Definition: execnodes.h:514
Oid es_lastoid
Definition: execnodes.h:530
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlannedStmt * es_plannedstmt
Definition: execnodes.h:481
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:479
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:547
Snapshot es_snapshot
Definition: execnodes.h:478
List * es_range_table
Definition: execnodes.h:480
ScanDirection es_direction
Definition: execnodes.h:477
bool es_use_parallel_mode
Definition: execnodes.h:562
const char * es_sourceText
Definition: execnodes.h:482
ParamExecData * es_param_exec_vals
Definition: execnodes.h:518
MemoryContext es_query_cxt
Definition: execnodes.h:523
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
int es_jit_flags
Definition: execnodes.h:572
ResultRelInfo * es_result_relations
Definition: execnodes.h:490
TupleTableSlot * es_trig_oldtup_slot
Definition: execnodes.h:513
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
int es_instrument
Definition: execnodes.h:533
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:512
QueryEnvironment * es_queryEnv
Definition: execnodes.h:520
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
int es_num_root_result_relations
Definition: execnodes.h:502
#define InvalidSnapshot
Definition: snapshot.h:25
List * es_trig_target_relations
Definition: execnodes.h:511
List * es_tupleTable
Definition: execnodes.h:525
List * es_auxmodifytables
Definition: execnodes.h:540
int es_num_result_relations
Definition: execnodes.h:491
#define InvalidOid
Definition: postgres_ext.h:36
List * es_tuple_routing_result_relations
Definition: execnodes.h:508
bool es_finished
Definition: execnodes.h:534
#define makeNode(_type_)
Definition: nodes.h:565
uint64 es_processed
Definition: execnodes.h:529
bool * es_epqTupleSet
Definition: execnodes.h:559
List * es_subplanstates
Definition: execnodes.h:538
List * es_rowMarks
Definition: execnodes.h:527
int es_top_eflags
Definition: execnodes.h:532
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:501
bool * es_epqScanDone
Definition: execnodes.h:560
ParamListInfo es_param_list_info
Definition: execnodes.h:517
List * es_exprcontexts
Definition: execnodes.h:536
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:492

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 228 of file execUtils.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ExprContext::caseValue_datum, ExprContext::caseValue_isNull, 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, EState::es_exprcontexts, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_query_cxt, lcons(), makeNode, and MemoryContextSwitchTo().

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

229 {
230  ExprContext *econtext;
231  MemoryContext oldcontext;
232 
233  /* Create the ExprContext node within the per-query memory context */
234  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
235 
236  econtext = makeNode(ExprContext);
237 
238  /* Initialize fields of ExprContext */
239  econtext->ecxt_scantuple = NULL;
240  econtext->ecxt_innertuple = NULL;
241  econtext->ecxt_outertuple = NULL;
242 
243  econtext->ecxt_per_query_memory = estate->es_query_cxt;
244 
245  /*
246  * Create working memory for expression evaluation in this context.
247  */
248  econtext->ecxt_per_tuple_memory =
250  "ExprContext",
252 
253  econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
254  econtext->ecxt_param_list_info = estate->es_param_list_info;
255 
256  econtext->ecxt_aggvalues = NULL;
257  econtext->ecxt_aggnulls = NULL;
258 
259  econtext->caseValue_datum = (Datum) 0;
260  econtext->caseValue_isNull = true;
261 
262  econtext->domainValue_datum = (Datum) 0;
263  econtext->domainValue_isNull = true;
264 
265  econtext->ecxt_estate = estate;
266 
267  econtext->ecxt_callbacks = NULL;
268 
269  /*
270  * Link the ExprContext into the EState to ensure it is shut down when the
271  * EState is freed. Because we use lcons(), shutdowns will occur in
272  * reverse order of creation, which may not be essential but can't hurt.
273  */
274  estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
275 
276  MemoryContextSwitchTo(oldcontext);
277 
278  return econtext;
279 }
Datum * ecxt_aggvalues
Definition: execnodes.h:237
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:226
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Datum domainValue_datum
Definition: execnodes.h:249
ParamExecData * es_param_exec_vals
Definition: execnodes.h:518
MemoryContext es_query_cxt
Definition: execnodes.h:523
Datum caseValue_datum
Definition: execnodes.h:243
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:257
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:220
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:229
struct EState * ecxt_estate
Definition: execnodes.h:254
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
bool domainValue_isNull
Definition: execnodes.h:251
bool * ecxt_aggnulls
Definition: execnodes.h:239
uintptr_t Datum
Definition: postgres.h:367
List * lcons(void *datum, List *list)
Definition: list.c:259
#define makeNode(_type_)
Definition: nodes.h:565
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:222
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:218
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:225
bool caseValue_isNull
Definition: execnodes.h:245
ParamListInfo es_param_list_info
Definition: execnodes.h:517
List * es_exprcontexts
Definition: execnodes.h:536
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:230

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 300 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 domain_check_input(), and hypothetical_dense_rank_final().

301 {
302  ExprContext *econtext;
303 
304  /* Create the ExprContext node within the caller's memory context */
305  econtext = makeNode(ExprContext);
306 
307  /* Initialize fields of ExprContext */
308  econtext->ecxt_scantuple = NULL;
309  econtext->ecxt_innertuple = NULL;
310  econtext->ecxt_outertuple = NULL;
311 
313 
314  /*
315  * Create working memory for expression evaluation in this context.
316  */
317  econtext->ecxt_per_tuple_memory =
319  "ExprContext",
321 
322  econtext->ecxt_param_exec_vals = NULL;
323  econtext->ecxt_param_list_info = NULL;
324 
325  econtext->ecxt_aggvalues = NULL;
326  econtext->ecxt_aggnulls = NULL;
327 
328  econtext->caseValue_datum = (Datum) 0;
329  econtext->caseValue_isNull = true;
330 
331  econtext->domainValue_datum = (Datum) 0;
332  econtext->domainValue_isNull = true;
333 
334  econtext->ecxt_estate = NULL;
335 
336  econtext->ecxt_callbacks = NULL;
337 
338  return econtext;
339 }
Datum * ecxt_aggvalues
Definition: execnodes.h:237
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:226
Datum domainValue_datum
Definition: execnodes.h:249
Datum caseValue_datum
Definition: execnodes.h:243
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:257
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:220
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:229
struct EState * ecxt_estate
Definition: execnodes.h:254
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
bool domainValue_isNull
Definition: execnodes.h:251
bool * ecxt_aggnulls
Definition: execnodes.h:239
uintptr_t Datum
Definition: postgres.h:367
#define makeNode(_type_)
Definition: nodes.h:565
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:222
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:218
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:225
bool caseValue_isNull
Definition: execnodes.h:245
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:230

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 1361 of file execTuples.c.

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

Referenced by ExplainQuery().

1362 {
1363  Datum values[1];
1364  bool isnull[1] = {false};
1365 
1366  while (*txt)
1367  {
1368  const char *eol;
1369  int len;
1370 
1371  eol = strchr(txt, '\n');
1372  if (eol)
1373  {
1374  len = eol - txt;
1375  eol++;
1376  }
1377  else
1378  {
1379  len = strlen(txt);
1380  eol = txt + len;
1381  }
1382 
1383  values[0] = PointerGetDatum(cstring_to_text_with_len(txt, len));
1384  do_tup_output(tstate, values, isnull);
1385  pfree(DatumGetPointer(values[0]));
1386  txt = eol;
1387  }
1388 }
#define PointerGetDatum(X)
Definition: postgres.h:541
void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
Definition: execTuples.c:1333
void pfree(void *pointer)
Definition: mcxt.c:1031
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetPointer(X)
Definition: postgres.h:534
static Datum values[MAXATTR]
Definition: bootstrap.c:164

◆ do_tup_output()

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

Definition at line 1333 of file execTuples.c.

References TupOutputState::dest, ExecClearTuple(), ExecStoreVirtualTuple(), tupleDesc::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().

1334 {
1335  TupleTableSlot *slot = tstate->slot;
1336  int natts = slot->tts_tupleDescriptor->natts;
1337 
1338  /* make sure the slot is clear */
1339  ExecClearTuple(slot);
1340 
1341  /* insert data */
1342  memcpy(slot->tts_values, values, natts * sizeof(Datum));
1343  memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
1344 
1345  /* mark slot as containing a virtual tuple */
1346  ExecStoreVirtualTuple(slot);
1347 
1348  /* send the tuple to the receiver */
1349  (void) tstate->dest->receiveSlot(slot, tstate->dest);
1350 
1351  /* clean up */
1352  ExecClearTuple(slot);
1353 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
Datum * tts_values
Definition: tuptable.h:130
TupleTableSlot * slot
Definition: executor.h:447
int natts
Definition: tupdesc.h:82
bool * tts_isnull
Definition: tuptable.h:132
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
uintptr_t Datum
Definition: postgres.h:367
static Datum values[MAXATTR]
Definition: bootstrap.c:164
DestReceiver * dest
Definition: executor.h:448
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:524

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 1391 of file execTuples.c.

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

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

1392 {
1393  tstate->dest->rShutdown(tstate->dest);
1394  /* note that destroying the dest is not ours to do */
1396  pfree(tstate);
1397 }
TupleTableSlot * slot
Definition: executor.h:447
void pfree(void *pointer)
Definition: mcxt.c:1031
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:247
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
DestReceiver * dest
Definition: executor.h:448

◆ EvalPlanQual()

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

Definition at line 2501 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate,
EState parentestate 
)

Definition at line 3060 of file execMain.c.

References bms_add_member(), PlanState::chgParam, EPQState::epqParam, EState::es_epqScanDone, EState::es_param_exec_vals, EState::es_plannedstmt, EState::es_range_table, EPQState::estate, EvalPlanQualStart(), i, ParamExecData::isnull, list_length(), MemSet, NIL, PlannedStmt::paramExecTypes, EPQState::plan, EPQState::planstate, and ParamExecData::value.

Referenced by EvalPlanQual(), and ExecLockRows().

3061 {
3062  EState *estate = epqstate->estate;
3063 
3064  if (estate == NULL)
3065  {
3066  /* First time through, so create a child EState */
3067  EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
3068  }
3069  else
3070  {
3071  /*
3072  * We already have a suitable child EPQ tree, so just reset it.
3073  */
3074  int rtsize = list_length(parentestate->es_range_table);
3075  PlanState *planstate = epqstate->planstate;
3076 
3077  MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
3078 
3079  /* Recopy current values of parent parameters */
3080  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
3081  {
3082  int i;
3083 
3084  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
3085 
3086  while (--i >= 0)
3087  {
3088  /* copy value if any, but not execPlan link */
3089  estate->es_param_exec_vals[i].value =
3090  parentestate->es_param_exec_vals[i].value;
3091  estate->es_param_exec_vals[i].isnull =
3092  parentestate->es_param_exec_vals[i].isnull;
3093  }
3094  }
3095 
3096  /*
3097  * Mark child plan tree as needing rescan at all scan nodes. The
3098  * first ExecProcNode will take care of actually doing the rescan.
3099  */
3100  planstate->chgParam = bms_add_member(planstate->chgParam,
3101  epqstate->epqParam);
3102  }
3103 }
List * paramExecTypes
Definition: plannodes.h:94
#define NIL
Definition: pg_list.h:69
PlannedStmt * es_plannedstmt
Definition: execnodes.h:481
#define MemSet(start, val, len)
Definition: c.h:908
List * es_range_table
Definition: execnodes.h:480
PlanState * planstate
Definition: execnodes.h:993
ParamExecData * es_param_exec_vals
Definition: execnodes.h:518
bool isnull
Definition: params.h:149
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
Definition: execMain.c:3112
Bitmapset * chgParam
Definition: execnodes.h:941
Plan * plan
Definition: execnodes.h:995
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
int i
bool * es_epqScanDone
Definition: execnodes.h:560
Datum value
Definition: params.h:148
int epqParam
Definition: execnodes.h:997
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 3253 of file execMain.c.

References EState::es_query_cxt, EState::es_subplanstates, EState::es_tupleTable, EPQState::estate, ExecCleanUpTriggerState(), ExecEndNode(), ExecResetTupleTable(), FreeExecutorState(), lfirst, MemoryContextSwitchTo(), EPQState::origslot, and EPQState::planstate.

Referenced by apply_handle_delete(), apply_handle_update(), EvalPlanQualSetPlan(), ExecEndLockRows(), and ExecEndModifyTable().

3254 {
3255  EState *estate = epqstate->estate;
3256  MemoryContext oldcontext;
3257  ListCell *l;
3258 
3259  if (estate == NULL)
3260  return; /* idle, so nothing to do */
3261 
3262  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3263 
3264  ExecEndNode(epqstate->planstate);
3265 
3266  foreach(l, estate->es_subplanstates)
3267  {
3268  PlanState *subplanstate = (PlanState *) lfirst(l);
3269 
3270  ExecEndNode(subplanstate);
3271  }
3272 
3273  /* throw away the per-estate tuple table */
3274  ExecResetTupleTable(estate->es_tupleTable, false);
3275 
3276  /* close any trigger target relations attached to this EState */
3277  ExecCleanUpTriggerState(estate);
3278 
3279  MemoryContextSwitchTo(oldcontext);
3280 
3281  FreeExecutorState(estate);
3282 
3283  /* Mark EPQState idle */
3284  epqstate->estate = NULL;
3285  epqstate->planstate = NULL;
3286  epqstate->origslot = NULL;
3287 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:538
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:993
void FreeExecutorState(EState *estate)
Definition: execUtils.c:188
MemoryContext es_query_cxt
Definition: execnodes.h:523
TupleTableSlot * origslot
Definition: execnodes.h:994
List * es_tupleTable
Definition: execnodes.h:525
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:186
#define lfirst(lc)
Definition: pg_list.h:106
List * es_subplanstates
Definition: execnodes.h:538
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1474
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualFetch()

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

Definition at line 2588 of file execMain.c.

References Assert, buffer, ConditionalXactLockTableWait(), HeapUpdateFailureData::ctid, elog, ereport, errcode(), errmsg(), ERROR, EState::es_output_cid, heap_copytuple(), heap_fetch(), heap_lock_tuple(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleHeaderIndicatesMovedPartitions, HeapTupleHeaderIsSpeculative, HeapTupleInvisible, HeapTupleMayBeUpdated, HeapTupleSelfUpdated, HeapTupleUpdated, HeapTupleWouldBlock, InitDirtySnapshot, IsolationUsesXactSnapshot, ItemPointerEquals(), ItemPointerIndicatesMovedPartitions, LockWaitBlock, LockWaitError, LockWaitSkip, RelationGetRelationName, ReleaseBuffer(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, test(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, XactLockTableWait(), XLTW_FetchUpdated, SnapshotData::xmax, HeapUpdateFailureData::xmax, and SnapshotData::xmin.

Referenced by EvalPlanQual(), and ExecLockRows().

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

◆ EvalPlanQualFetchRowMarks()

void EvalPlanQualFetchRowMarks ( EPQState epqstate)

Definition at line 2900 of file execMain.c.

References EPQState::arowMarks, Assert, buffer, ExecAuxRowMark::ctidAttNo, DatumGetHeapTupleHeader, DatumGetObjectId, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, EPQState::estate, EvalPlanQualSetTuple(), ExecGetJunkAttribute(), GetFdwRoutineForRelation(), heap_copytuple(), heap_expand_tuple(), heap_fetch(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetNatts, lfirst, ExecRowMark::markType, OidIsValid, EPQState::origslot, ExecRowMark::prti, RelationData::rd_rel, FdwRoutine::RefetchForeignRow, ExecRowMark::relation, RelationGetDescr, RelationGetRelationName, ReleaseBuffer(), ExecRowMark::relid, ROW_MARK_COPY, ROW_MARK_REFERENCE, ExecAuxRowMark::rowmark, RowMarkRequiresRowShareLock, ExecRowMark::rti, SnapshotAny, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, ExecAuxRowMark::toidAttNo, and ExecAuxRowMark::wholeAttNo.

Referenced by EvalPlanQual(), and ExecLockRows().

2901 {
2902  ListCell *l;
2903 
2904  Assert(epqstate->origslot != NULL);
2905 
2906  foreach(l, epqstate->arowMarks)
2907  {
2908  ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
2909  ExecRowMark *erm = aerm->rowmark;
2910  Datum datum;
2911  bool isNull;
2912  HeapTupleData tuple;
2913 
2915  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2916 
2917  /* clear any leftover test tuple for this rel */
2918  EvalPlanQualSetTuple(epqstate, erm->rti, NULL);
2919 
2920  /* if child rel, must check whether it produced this row */
2921  if (erm->rti != erm->prti)
2922  {
2923  Oid tableoid;
2924 
2925  datum = ExecGetJunkAttribute(epqstate->origslot,
2926  aerm->toidAttNo,
2927  &isNull);
2928  /* non-locked rels could be on the inside of outer joins */
2929  if (isNull)
2930  continue;
2931  tableoid = DatumGetObjectId(datum);
2932 
2933  Assert(OidIsValid(erm->relid));
2934  if (tableoid != erm->relid)
2935  {
2936  /* this child is inactive right now */
2937  continue;
2938  }
2939  }
2940 
2941  if (erm->markType == ROW_MARK_REFERENCE)
2942  {
2943  HeapTuple copyTuple;
2944 
2945  Assert(erm->relation != NULL);
2946 
2947  /* fetch the tuple's ctid */
2948  datum = ExecGetJunkAttribute(epqstate->origslot,
2949  aerm->ctidAttNo,
2950  &isNull);
2951  /* non-locked rels could be on the inside of outer joins */
2952  if (isNull)
2953  continue;
2954 
2955  /* fetch requests on foreign tables must be passed to their FDW */
2956  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2957  {
2958  FdwRoutine *fdwroutine;
2959  bool updated = false;
2960 
2961  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2962  /* this should have been checked already, but let's be safe */
2963  if (fdwroutine->RefetchForeignRow == NULL)
2964  ereport(ERROR,
2965  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2966  errmsg("cannot lock rows in foreign table \"%s\"",
2968  copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate,
2969  erm,
2970  datum,
2971  &updated);
2972  if (copyTuple == NULL)
2973  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2974 
2975  /*
2976  * Ideally we'd insist on updated == false here, but that
2977  * assumes that FDWs can track that exactly, which they might
2978  * not be able to. So just ignore the flag.
2979  */
2980  }
2981  else
2982  {
2983  /* ordinary table, fetch the tuple */
2984  Buffer buffer;
2985 
2986  tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
2987  if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
2988  false, NULL))
2989  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2990 
2991  if (HeapTupleHeaderGetNatts(tuple.t_data) <
2992  RelationGetDescr(erm->relation)->natts)
2993  {
2994  copyTuple = heap_expand_tuple(&tuple,
2995  RelationGetDescr(erm->relation));
2996  }
2997  else
2998  {
2999  /* successful, copy tuple */
3000  copyTuple = heap_copytuple(&tuple);
3001  }
3002  ReleaseBuffer(buffer);
3003  }
3004 
3005  /* store tuple */
3006  EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
3007  }
3008  else
3009  {
3010  HeapTupleHeader td;
3011 
3012  Assert(erm->markType == ROW_MARK_COPY);
3013 
3014  /* fetch the whole-row Var for the relation */
3015  datum = ExecGetJunkAttribute(epqstate->origslot,
3016  aerm->wholeAttNo,
3017  &isNull);
3018  /* non-locked rels could be on the inside of outer joins */
3019  if (isNull)
3020  continue;
3021  td = DatumGetHeapTupleHeader(datum);
3022 
3023  /* build a temporary HeapTuple control structure */
3025  tuple.t_data = td;
3026  /* relation might be a foreign table, if so provide tableoid */
3027  tuple.t_tableOid = erm->relid;
3028  /* also copy t_ctid in case there's valid data there */
3029  tuple.t_self = td->t_ctid;
3030 
3031  /* copy and store tuple */
3032  EvalPlanQualSetTuple(epqstate, erm->rti,
3033  heap_copytuple(&tuple));
3034  }
3035  }
3036 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:722
#define RelationGetDescr(relation)
Definition: rel.h:433
void EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
Definition: execMain.c:2865
Relation relation
Definition: execnodes.h:596
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1903
#define DatumGetObjectId(X)
Definition: postgres.h:485
int errcode(int sqlerrcode)
Definition: elog.c:575
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:264
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:994
ItemPointerData * ItemPointer
Definition: itemptr.h:49
ExecRowMark * rowmark
Definition: execnodes.h:623
HeapTupleHeader t_data
Definition: htup.h:68
#define ERROR
Definition: elog.h:43
#define HeapTupleHeaderGetNatts(tup)
Definition: htup_details.h:544
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
List * arowMarks
Definition: execnodes.h:996
uint32 t_len
Definition: htup.h:64
Index rti
Definition: execnodes.h:598
AttrNumber wholeAttNo
Definition: execnodes.h:626
Index prti
Definition: execnodes.h:599
HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition: heaptuple.c:1023
#define RelationGetRelationName(relation)
Definition: rel.h:441
Oid t_tableOid
Definition: htup.h:66
TupleTableSlot * origslot
Definition: execnodes.h:994
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:367
#define SnapshotAny
Definition: tqual.h:28
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
RowMarkType markType
Definition: execnodes.h:601
AttrNumber toidAttNo
Definition: execnodes.h:625
#define DatumGetPointer(X)
Definition: postgres.h:534
int errmsg(const char *fmt,...)
Definition: elog.c:797
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: execJunk.c:248
#define elog
Definition: elog.h:219
EState * estate
Definition: execnodes.h:992
int Buffer
Definition: buf.h:23
AttrNumber ctidAttNo
Definition: execnodes.h:624
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:224
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451

◆ EvalPlanQualGetTuple()

HeapTuple EvalPlanQualGetTuple ( EPQState epqstate,
Index  rti 
)

Definition at line 2885 of file execMain.c.

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

2886 {
2887  EState *estate = epqstate->estate;
2888 
2889  Assert(rti > 0);
2890 
2891  return estate->es_epqTuple[rti - 1];
2892 }
HeapTuple * es_epqTuple
Definition: execnodes.h:558
#define Assert(condition)
Definition: c.h:699
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualInit()

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

Definition at line 2830 of file execMain.c.

References EPQState::arowMarks, EPQState::epqParam, EPQState::estate, EPQState::origslot, EPQState::plan, and EPQState::planstate.

Referenced by apply_handle_delete(), apply_handle_update(), ExecInitLockRows(), and ExecInitModifyTable().

2832 {
2833  /* Mark the EPQ state inactive */
2834  epqstate->estate = NULL;
2835  epqstate->planstate = NULL;
2836  epqstate->origslot = NULL;
2837  /* ... and remember data that EvalPlanQualBegin will need */
2838  epqstate->plan = subplan;
2839  epqstate->arowMarks = auxrowmarks;
2840  epqstate->epqParam = epqParam;
2841 }
PlanState * planstate
Definition: execnodes.h:993
List * arowMarks
Definition: execnodes.h:996
TupleTableSlot * origslot
Definition: execnodes.h:994
Plan * plan
Definition: execnodes.h:995
int epqParam
Definition: execnodes.h:997
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 3044 of file execMain.c.

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

Referenced by EvalPlanQual(), and ExecLockRows().

3045 {
3046  MemoryContext oldcontext;
3047  TupleTableSlot *slot;
3048 
3049  oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
3050  slot = ExecProcNode(epqstate->planstate);
3051  MemoryContextSwitchTo(oldcontext);
3052 
3053  return slot;
3054 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:993
MemoryContext es_query_cxt
Definition: execnodes.h:523
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:233
EState * estate
Definition: execnodes.h:992

◆ EvalPlanQualSetPlan()

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

Definition at line 2849 of file execMain.c.

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

Referenced by ExecInitModifyTable(), and ExecModifyTable().

2850 {
2851  /* If we have a live EPQ query, shut it down */
2852  EvalPlanQualEnd(epqstate);
2853  /* And set/change the plan pointer */
2854  epqstate->plan = subplan;
2855  /* The rowmarks depend on the plan, too */
2856  epqstate->arowMarks = auxrowmarks;
2857 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3253
List * arowMarks
Definition: execnodes.h:996
Plan * plan
Definition: execnodes.h:995

◆ EvalPlanQualSetTuple()

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

Definition at line 2865 of file execMain.c.

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

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

2866 {
2867  EState *estate = epqstate->estate;
2868 
2869  Assert(rti > 0);
2870 
2871  /*
2872  * free old test tuple, if any, and store new tuple where relation's scan
2873  * node will see it
2874  */
2875  if (estate->es_epqTuple[rti - 1] != NULL)
2876  heap_freetuple(estate->es_epqTuple[rti - 1]);
2877  estate->es_epqTuple[rti - 1] = tuple;
2878  estate->es_epqTupleSet[rti - 1] = true;
2879 }
HeapTuple * es_epqTuple
Definition: execnodes.h:558
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
#define Assert(condition)
Definition: c.h:699
bool * es_epqTupleSet
Definition: execnodes.h:559
EState * estate
Definition: execnodes.h:992

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

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

458 {
459  planstate->ps_ProjInfo =
461  planstate->ps_ExprContext,
462  planstate->ps_ResultTupleSlot,
463  planstate,
464  inputDesc);
465 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:948
ExprContext * ps_ExprContext
Definition: execnodes.h:947
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:946
Plan * plan
Definition: execnodes.h:912
List * targetlist
Definition: plannodes.h:146
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:349

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
Index  varno 
)

Definition at line 248 of file execScan.c.

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

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

249 {
251 
252  ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, varno);
253 }
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1195
void ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc, Index varno)
Definition: execUtils.c:476
PlanState ps
Definition: execnodes.h:1192
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 586 of file execUtils.c.

References ExecSetSlotDescriptor(), and ScanState::ss_ScanTupleSlot.

Referenced by ExecWorkTableScan().

587 {
588  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
589 
590  ExecSetSlotDescriptor(slot, tupDesc);
591 }
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1195
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:281

◆ ExecBuildAggTrans()

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

Referenced by ExecProcNode().

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

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

2431 {
2432  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2433  char resname[32];
2434 
2435  aerm->rowmark = erm;
2436 
2437  /* Look up the resjunk columns associated with this rowmark */
2438  if (erm->markType != ROW_MARK_COPY)
2439  {
2440  /* need ctid for all methods other than COPY */
2441  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2442  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2443  resname);
2444  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2445  elog(ERROR, "could not find junk %s column", resname);
2446  }
2447  else
2448  {
2449  /* need wholerow if COPY */
2450  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2451  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2452  resname);
2453  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2454  elog(ERROR, "could not find junk %s column", resname);
2455  }
2456 
2457  /* if child rel, need tableoid */
2458  if (erm->rti != erm->prti)
2459  {
2460  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2461  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2462  resname);
2463  if (!AttributeNumberIsValid(aerm->toidAttNo))
2464  elog(ERROR, "could not find junk %s column", resname);
2465  }
2466 
2467  return aerm;
2468 }
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:221
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
ExecRowMark * rowmark
Definition: execnodes.h:623
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:598
AttrNumber wholeAttNo
Definition: execnodes.h:626
Index prti
Definition: execnodes.h:599
Index rowmarkId
Definition: execnodes.h:600
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void * palloc0(Size size)
Definition: mcxt.c:955
RowMarkType markType
Definition: execnodes.h:601
AttrNumber toidAttNo
Definition: execnodes.h:625
#define elog
Definition: elog.h:219
AttrNumber ctidAttNo
Definition: execnodes.h:624

◆ ExecBuildGroupingEqual()

ExprState* ExecBuildGroupingEqual ( TupleDesc  ldesc,
TupleDesc  rdesc,
int  numCols,
AttrNumber keyColIdx,
Oid eqfunctions,
PlanState parent 
)

Definition at line 3216 of file execExpr.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, 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, ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprEvalStep::fetch, ExprState::flags, fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_addr, ExprEvalStep::func, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvalidOid, InvokeFunctionExecuteHook, 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, ExprState::steps, ExprState::steps_len, TupleDescAttr, and ExprEvalStep::var.

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

3221 {
3223  ExprEvalStep scratch = {0};
3224  int natt;
3225  int maxatt = -1;
3226  List *adjust_jumps = NIL;
3227  ListCell *lc;
3228 
3229  /*
3230  * When no columns are actually compared, the result's always true. See
3231  * special case in ExecQual().
3232  */
3233  if (numCols == 0)
3234  return NULL;
3235 
3236  state->expr = NULL;
3237  state->flags = EEO_FLAG_IS_QUAL;
3238  state->parent = parent;
3239 
3240  scratch.resvalue = &state->resvalue;
3241  scratch.resnull = &state->resnull;
3242 
3243  /* compute max needed attribute */
3244  for (natt = 0; natt < numCols; natt++)
3245  {
3246  int attno = keyColIdx[natt];
3247 
3248  if (attno > maxatt)
3249  maxatt = attno;
3250  }
3251  Assert(maxatt >= 0);
3252 
3253  /* push deform steps */
3254  scratch.opcode = EEOP_INNER_FETCHSOME;
3255  scratch.d.fetch.last_var = maxatt;
3256  scratch.d.fetch.known_desc = ldesc;
3257  ExprEvalPushStep(state, &scratch);
3258 
3259  scratch.opcode = EEOP_OUTER_FETCHSOME;
3260  scratch.d.fetch.last_var = maxatt;
3261  scratch.d.fetch.known_desc = rdesc;
3262  ExprEvalPushStep(state, &scratch);
3263 
3264  /*
3265  * Start comparing at the last field (least significant sort key). That's
3266  * the most likely to be different if we are dealing with sorted input.
3267  */
3268  for (natt = numCols; --natt >= 0;)
3269  {
3270  int attno = keyColIdx[natt];
3271  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3272  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3273  Oid foid = eqfunctions[natt];
3274  FmgrInfo *finfo;
3275  FunctionCallInfo fcinfo;
3276  AclResult aclresult;
3277 
3278  /* Check permission to call function */
3279  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
3280  if (aclresult != ACLCHECK_OK)
3281  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3282 
3284 
3285  /* Set up the primary fmgr lookup information */
3286  finfo = palloc0(sizeof(FmgrInfo));
3287  fcinfo = palloc0(sizeof(FunctionCallInfoData));
3288  fmgr_info(foid, finfo);
3289  fmgr_info_set_expr(NULL, finfo);
3290  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3291  InvalidOid, NULL, NULL);
3292 
3293  /* left arg */
3294  scratch.opcode = EEOP_INNER_VAR;
3295  scratch.d.var.attnum = attno - 1;
3296  scratch.d.var.vartype = latt->atttypid;
3297  scratch.resvalue = &fcinfo->arg[0];
3298  scratch.resnull = &fcinfo->argnull[0];
3299  ExprEvalPushStep(state, &scratch);
3300 
3301  /* right arg */
3302  scratch.opcode = EEOP_OUTER_VAR;
3303  scratch.d.var.attnum = attno - 1;
3304  scratch.d.var.vartype = ratt->atttypid;
3305  scratch.resvalue = &fcinfo->arg[1];
3306  scratch.resnull = &fcinfo->argnull[1];
3307  ExprEvalPushStep(state, &scratch);
3308 
3309  /* evaluate distinctness */
3310  scratch.opcode = EEOP_NOT_DISTINCT;
3311  scratch.d.func.finfo = finfo;
3312  scratch.d.func.fcinfo_data = fcinfo;
3313  scratch.d.func.fn_addr = finfo->fn_addr;
3314  scratch.d.func.nargs = 2;
3315  scratch.resvalue = &state->resvalue;
3316  scratch.resnull = &state->resnull;
3317  ExprEvalPushStep(state, &scratch);
3318 
3319  /* then emit EEOP_QUAL to detect if result is false (or null) */
3320  scratch.opcode = EEOP_QUAL;
3321  scratch.d.qualexpr.jumpdone = -1;
3322  scratch.resvalue = &state->resvalue;
3323  scratch.resnull = &state->resnull;
3324  ExprEvalPushStep(state, &scratch);
3325  adjust_jumps = lappend_int(adjust_jumps,
3326  state->steps_len - 1);
3327  }
3328 
3329  /* adjust jump targets */
3330  foreach(lc, adjust_jumps)
3331  {
3332  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3333 
3334  Assert(as->opcode == EEOP_QUAL);
3335  Assert(as->d.qualexpr.jumpdone == -1);
3336  as->d.qualexpr.jumpdone = state->steps_len;
3337  }
3338 
3339  scratch.resvalue = NULL;
3340  scratch.resnull = NULL;
3341  scratch.opcode = EEOP_DONE;
3342  ExprEvalPushStep(state, &scratch);
3343 
3344  ExecReadyExpr(state);
3345 
3346  return state;
3347 }
#define NIL
Definition: pg_list.h:69
Definition: fmgr.h:56
struct PlanState * parent
Definition: execnodes.h:103
struct ExprEvalStep::@52::@54 var
Datum * resvalue
Definition: execExpr.h:249
Oid GetUserId(void)
Definition: miscinit.c:379
PGFunction fn_addr
Definition: fmgr.h:58
struct ExprEvalStep * steps
Definition: execnodes.h:81
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
bool * resnull
Definition: execExpr.h:250
unsigned int Oid
Definition: postgres_ext.h:31
union ExprEvalStep::@52 d
struct ExprEvalStep::@52::@61 qualexpr
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
struct ExprEvalStep::@52::@53 fetch
bool resnull
Definition: execnodes.h:68
Expr * expr
Definition: execnodes.h:90
#define lfirst_int(lc)
Definition: pg_list.h:107
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1397
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:55
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:107
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:89
List * lappend_int(List *list, int datum)
Definition: list.c:146
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
void * palloc0(Size size)
Definition: mcxt.c:955
AclResult
Definition: acl.h:178
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2130
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:625
#define InvalidOid
Definition: postgres_ext.h:36
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:87
struct ExprEvalStep::@52::@59 func
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:246
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:125
int steps_len
Definition: execnodes.h:100
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4651
uint8 flags
Definition: execnodes.h:61
Definition: pg_list.h:45
Datum resvalue
Definition: execnodes.h:70

◆ ExecBuildProjectionInfo()

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

Definition at line 349 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, Node::type, Var::varattno, Var::varno, and Var::vartype.

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

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext context 
)

Definition at line 595 of file execExpr.c.

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

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

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

◆ ExecCheckIndexConstraints()

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

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

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

◆ ExecCheckRTPerms()

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

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

575 {
576  ListCell *l;
577  bool result = true;
578 
579  foreach(l, rangeTable)
580  {
581  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
582 
583  result = ExecCheckRTEPerms(rte);
584  if (!result)
585  {
586  Assert(rte->rtekind == RTE_RELATION);
587  if (ereport_on_violation)
589  get_rel_name(rte->relid));
590  return false;
591  }
592  }
593 
595  result = (*ExecutorCheckPerms_hook) (rangeTable,
596  ereport_on_violation);
597  return result;
598 }
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
static bool ExecCheckRTEPerms(RangeTblEntry *rte)
Definition: execMain.c:605
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:76
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
RTEKind rtekind
Definition: parsenodes.h:962
ObjectType get_relkind_objtype(char relkind)
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1049 of file execUtils.c.

References lfirst_node, and TargetEntry::resjunk.

Referenced by check_sql_fn_retval(), and ExecTypeFromTLInternal().

1050 {
1051  int len = 0;
1052  ListCell *tl;
1053 
1054  foreach(tl, targetlist)
1055  {
1056  TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1057 
1058  if (!curTle->resjunk)
1059  len++;
1060  }
1061  return len;
1062 }
bool resjunk
Definition: primnodes.h:1383
#define lfirst_node(type, lc)
Definition: pg_list.h:109

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList,
bool  hasoid 
)

Definition at line 977 of file execTuples.c.

References ExecTypeFromTLInternal().

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

978 {
979  return ExecTypeFromTLInternal(targetList, hasoid, true);
980 }
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk)
Definition: execTuples.c:983

◆ ExecCleanUpTriggerState()

void ExecCleanUpTriggerState ( EState estate)

Definition at line 1474 of file execMain.c.

References EState::es_trig_target_relations, ExecCloseIndices(), heap_close, lfirst, NoLock, and ResultRelInfo::ri_RelationDesc.

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

1475 {
1476  ListCell *l;
1477 
1478  foreach(l, estate->es_trig_target_relations)
1479  {
1480  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1481 
1482  /* Close indices and then the relation itself */
1483  ExecCloseIndices(resultRelInfo);
1484  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1485  }
1486 }
Relation ri_RelationDesc
Definition: execnodes.h:397
#define heap_close(r, l)
Definition: heapam.h:97
#define NoLock
Definition: lockdefs.h:34
List * es_trig_target_relations
Definition: execnodes.h:511
#define lfirst(lc)
Definition: pg_list.h:106
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:224

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 224 of file execIndexing.c.

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

Referenced by apply_handle_delete(), apply_handle_insert(), apply_handle_update(), CatalogCloseIndexes(), CopyFrom(), ExecCleanUpTriggerState(), ExecCleanupTupleRouting(), and ExecEndPlan().

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

◆ ExecCloseScanRelation()

void ExecCloseScanRelation ( Relation  scanrel)

Definition at line 701 of file execUtils.c.

References heap_close, and NoLock.

Referenced by ExecEndBitmapHeapScan(), ExecEndCustomScan(), ExecEndForeignScan(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), ExecEndSampleScan(), ExecEndSeqScan(), ExecEndTidScan(), and postgresEndDirectModify().

702 {
703  heap_close(scanrel, NoLock);
704 }
#define heap_close(r, l)
Definition: heapam.h:97
#define NoLock
Definition: lockdefs.h:34

◆ ExecConditionalAssignProjectionInfo()

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

Definition at line 476 of file execUtils.c.

References ExecAssignProjectionInfo(), PlanState::plan, PlanState::ps_ProjInfo, Plan::targetlist, and tlist_matches_tupdesc().

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

478 {
479  if (tlist_matches_tupdesc(planstate,
480  planstate->plan->targetlist,
481  varno,
482  inputDesc))
483  planstate->ps_ProjInfo = NULL;
484  else
485  ExecAssignProjectionInfo(planstate, inputDesc);
486 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:948
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:456
Plan * plan
Definition: execnodes.h:912
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
Definition: execUtils.c:489
List * targetlist
Definition: plannodes.h:146

◆ ExecConstraints()

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

Definition at line 1962 of file execMain.c.

References Assert, bms_union(), tupleDesc::constr, convert_tuples_by_name(), do_convert_tuple(), ereport, errcode(), errdetail(), errmsg(), ERROR, errtablecol(), errtableconstraint(), ExecBuildSlotValueDescription(), ExecFetchSlotTuple(), ExecPartitionCheck(), ExecPartitionCheckEmitError(), ExecRelCheck(), ExecSetSlotDescriptor(), ExecStoreTuple(), GetInsertedColumns, gettext_noop, GetUpdatedColumns, tupleConstr::has_not_null, InvalidBuffer, NameStr, tupleDesc::natts, tupleConstr::num_check, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ResultRelInfo::ri_PartitionCheck, ResultRelInfo::ri_PartitionRoot, ResultRelInfo::ri_RelationDesc, slot_attisnull(), and TupleDescAttr.

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

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

◆ ExecContextForcesOids()

bool ExecContextForcesOids ( PlanState planstate,
bool hasoids 
)

Definition at line 1521 of file execMain.c.

References EState::es_result_relation_info, EState::es_top_eflags, EXEC_FLAG_WITH_OIDS, EXEC_FLAG_WITHOUT_OIDS, RelationData::rd_rel, ResultRelInfo::ri_RelationDesc, and PlanState::state.

Referenced by ExecInitResultTupleSlotTL(), and tlist_matches_tupdesc().

1522 {
1523  ResultRelInfo *ri = planstate->state->es_result_relation_info;
1524 
1525  if (ri != NULL)
1526  {
1527  Relation rel = ri->ri_RelationDesc;
1528 
1529  if (rel != NULL)
1530  {
1531  *hasoids = rel->rd_rel->relhasoids;
1532  return true;
1533  }
1534  }
1535 
1536  if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS)
1537  {
1538  *hasoids = true;
1539  return true;
1540  }
1541  if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS)
1542  {
1543  *hasoids = false;
1544  return true;
1545  }
1546 
1547  return false;
1548 }
Relation ri_RelationDesc
Definition: execnodes.h:397
EState * state
Definition: execnodes.h:914
Form_pg_class rd_rel
Definition: rel.h:84
#define EXEC_FLAG_WITHOUT_OIDS
Definition: executor.h:64
#define EXEC_FLAG_WITH_OIDS
Definition: executor.h:63
int es_top_eflags
Definition: execnodes.h:532
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:492

◆ ExecCreateScanSlotFromOuterPlan()

void ExecCreateScanSlotFromOuterPlan ( EState estate,
ScanState scanstate 
)

Definition at line 598 of file execUtils.c.

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

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

599 {
601  TupleDesc tupDesc;
602 
603  outerPlan = outerPlanState(scanstate);
604  tupDesc = ExecGetResultType(outerPlan);
605 
606  ExecInitScanTupleSlot(estate, scanstate, tupDesc);
607 }
#define outerPlanState(node)
Definition: execnodes.h:966
#define outerPlan(node)
Definition: plannodes.h:176
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:438
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
Definition: execTuples.c:915

◆ execCurrentOf()

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

Definition at line 42 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_rowMarks, QueryDesc::estate, fetch_cursor_param_value(), get_rel_name(), GetPortalByName(), IsA, ItemPointerIsValid, lfirst, ExecRowMark::markType, QueryDesc::planstate, PORTAL_ONE_SELECT, PortalIsValid, PortalData::queryDesc, ExecRowMark::relid, RowMarkRequiresRowShareLock, search_plan_tree(), SelfItemPointerAttributeNumber, slot_getsysattr(), ScanState::ss_ScanTupleSlot, PortalData::strategy, HeapTupleData::t_self, TableOidAttributeNumber, TupIsNull, and IndexScanDescData::xs_ctup.

Referenced by TidListEval().

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

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 538 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(), 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_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(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndPlan(), ExecEndProjectSet(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndUnique(), and ExecEndWindowAgg().

539 {
540  /*
541  * do nothing when we get to the end of a leaf on tree.
542  */
543  if (node == NULL)
544  return;
545 
546  /*
547  * Make sure there's enough stack available. Need to check here, in
548  * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
549  * guaranteed that ExecProcNode() is reached for all nodes.
550  */
552 
553  if (node->chgParam != NULL)
554  {
555  bms_free(node->chgParam);
556  node->chgParam = NULL;
557  }
558 
559  switch (nodeTag(node))
560  {
561  /*
562  * control nodes
563  */
564  case T_ResultState:
565  ExecEndResult((ResultState *) node);
566  break;
567 
568  case T_ProjectSetState:
570  break;
571 
572  case T_ModifyTableState:
574  break;
575 
576  case T_AppendState:
577  ExecEndAppend((AppendState *) node);
578  break;
579 
580  case T_MergeAppendState:
582  break;
583 
586  break;
587 
588  case T_BitmapAndState:
590  break;
591 
592  case T_BitmapOrState:
593  ExecEndBitmapOr((BitmapOrState *) node);
594  break;
595 
596  /*
597  * scan nodes
598  */
599  case T_SeqScanState:
600  ExecEndSeqScan((SeqScanState *) node);
601  break;
602 
603  case T_SampleScanState:
605  break;
606 
607  case T_GatherState:
608  ExecEndGather((GatherState *) node);
609  break;
610 
611  case T_GatherMergeState:
613  break;
614 
615  case T_IndexScanState:
617  break;
618 
621  break;
622 
625  break;
626 
629  break;
630 
631  case T_TidScanState:
632  ExecEndTidScan((TidScanState *) node);
633  break;
634 
635  case T_SubqueryScanState:
637  break;
638 
639  case T_FunctionScanState:
641  break;
642 
645  break;
646 
647  case T_ValuesScanState:
649  break;
650 
651  case T_CteScanState:
652  ExecEndCteScan((CteScanState *) node);
653  break;
654 
657  break;
658 
661  break;
662 
663  case T_ForeignScanState:
665  break;
666 
667  case T_CustomScanState:
669  break;
670 
671  /*
672  * join nodes
673  */
674  case T_NestLoopState:
675  ExecEndNestLoop((NestLoopState *) node);
676  break;
677 
678  case T_MergeJoinState:
680  break;
681 
682  case T_HashJoinState:
683  ExecEndHashJoin((HashJoinState *) node);
684  break;
685 
686  /*
687  * materialization nodes
688  */
689  case T_MaterialState:
690  ExecEndMaterial((MaterialState *) node);
691  break;
692 
693  case T_SortState:
694  ExecEndSort((SortState *) node);
695  break;
696 
697  case T_GroupState:
698  ExecEndGroup((GroupState *) node);
699  break;
700 
701  case T_AggState:
702  ExecEndAgg((AggState *) node);
703  break;
704 
705  case T_WindowAggState:
707  break;
708 
709  case T_UniqueState:
710  ExecEndUnique((UniqueState *) node);
711  break;
712 
713  case T_HashState:
714  ExecEndHash((HashState *) node);
715  break;
716 
717  case T_SetOpState:
718  ExecEndSetOp((SetOpState *) node);
719  break;
720 
721  case T_LockRowsState:
722  ExecEndLockRows((LockRowsState *) node);
723  break;
724 
725  case T_LimitState:
726  ExecEndLimit((LimitState *) node);
727  break;
728 
729  default:
730  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
731  break;
732  }
733 }
void ExecEndGroup(GroupState *node)
Definition: nodeGroup.c:224
void ExecEndSetOp(SetOpState *node)
Definition: nodeSetOp.c:579
void ExecEndFunctionScan(FunctionScanState *node)
void ExecEndNestLoop(NestLoopState *node)
Definition: nodeNestloop.c:361
void ExecEndIndexScan(IndexScanState *node)
void ExecEndLimit(LimitState *node)
Definition: nodeLimit.c:393
void ExecEndUnique(UniqueState *node)
Definition: nodeUnique.c:168
void ExecEndGatherMerge(GatherMergeState *node)
void ExecEndWorkTableScan(WorkTableScanState *node)
void ExecEndLockRows(LockRowsState *node)
Definition: nodeLockRows.c:458
void ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
void ExecEndBitmapAnd(BitmapAndState *node)
void ExecEndRecursiveUnion(RecursiveUnionState *node)
void ExecEndSubqueryScan(SubqueryScanState *node)
void ExecEndHashJoin(HashJoinState *node)
Definition: nodeHashjoin.c:760
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:319
void ExecEndForeignScan(ForeignScanState *node)
void ExecEndSort(SortState *node)
Definition: nodeSort.c:234
void ExecEndBitmapIndexScan(BitmapIndexScanState *node)
void check_stack_depth(void)
Definition: postgres.c:3159
void ExecEndValuesScan(ValuesScanState *node)
void ExecEndMergeJoin(MergeJoinState *node)
void ExecEndSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:203
void ExecEndIndexOnlyScan(IndexOnlyScanState *node)
void ExecEndTidScan(TidScanState *node)
Definition: nodeTidscan.c:482
Bitmapset * chgParam
Definition: execnodes.h:941
void ExecEndCteScan(CteScanState *node)
Definition: nodeCtescan.c:287
void ExecEndCustomScan(CustomScanState *node)
Definition: nodeCustom.c:118
void ExecEndBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:196
void ExecEndSampleScan(SampleScanState *node)
void bms_free(Bitmapset *a)
Definition: bitmapset.c:267
void ExecEndWindowAgg(WindowAggState *node)
void ExecEndMergeAppend(MergeAppendState *node)
#define nodeTag(nodeptr)
Definition: nodes.h:522
void ExecEndHash(HashState *node)
Definition: nodeHash.c:404
void ExecEndProjectSet(ProjectSetState *node)
void ExecEndMaterial(MaterialState *node)
Definition: nodeMaterial.c:242
#define elog
Definition: elog.h:219
void ExecEndBitmapHeapScan(BitmapHeapScanState *node)
void ExecEndAgg(AggState *node)
Definition: nodeAgg.c:3308
void ExecEndModifyTable(ModifyTableState *node)
void ExecEndGather(GatherState *node)
Definition: nodeGather.c:229

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

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

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

299 {
300  Datum retDatum;
301  MemoryContext oldContext;
302 
303  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
304  retDatum = state->evalfunc(state, econtext, isNull);
305  MemoryContextSwitchTo(oldContext);
306  return retDatum;
307 }
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:226
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprStateEvalFunc evalfunc
Definition: execnodes.h:87
uintptr_t Datum
Definition: postgres.h:367

◆ ExecFilterJunk()

TupleTableSlot* ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 262 of file execJunk.c.

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

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

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

◆ ExecFindJunkAttribute()

AttrNumber ExecFindJunkAttribute ( JunkFilter junkfilter,
const char *  attrName 
)

Definition at line 209 of file execJunk.c.

References ExecFindJunkAttributeInTlist(), and JunkFilter::jf_targetList.

Referenced by ExecInitModifyTable().

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

◆ ExecFindJunkAttributeInTlist()

AttrNumber ExecFindJunkAttributeInTlist ( List targetlist,
const char *  attrName 
)

Definition at line 221 of file execJunk.c.

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

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

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

◆ ExecFindRowMark()

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

Definition at line 2406 of file execMain.c.

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

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

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

◆ ExecFreeExprContext()

◆ ExecGetJunkAttribute()

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

Definition at line 248 of file execJunk.c.

References Assert, and slot_getattr().

Referenced by EvalPlanQualFetchRowMarks(), ExecLockRows(), ExecModifyTable(), postgresExecForeignDelete(), and postgresExecForeignUpdate().

250 {
251  Assert(attno > 0);
252 
253  return slot_getattr(slot, attno, isNull);
254 }
#define Assert(condition)
Definition: c.h:699
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1518

◆ ExecGetResultType()

◆ ExecGetTriggerResultRel()

ResultRelInfo* ExecGetTriggerResultRel ( EState estate,
Oid  relid 
)

Definition at line 1392 of file execMain.c.

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

Referenced by afterTriggerInvokeEvents().

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