PostgreSQL Source Code  git master
executor.h File Reference
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)
 
bool execTuplesMatch (TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
 
bool execTuplesUnequal (TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
 
FmgrInfoexecTuplesMatchPrepare (int numCols, Oid *eqOperators)
 
void execTuplesHashPrepare (int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions)
 
TupleHashTable BuildTupleHashTable (int numCols, AttrNumber *keyColIdx, FmgrInfo *eqfunctions, 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, FmgrInfo *eqfunctions, 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)
 
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)
 
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 ExecInitResultTupleSlot (EState *estate, PlanState *planstate)
 
void ExecInitScanTupleSlot (EState *estate, ScanState *scanstate)
 
TupleTableSlotExecInitExtraTupleSlot (EState *estate)
 
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)
 
void ExecAssignResultType (PlanState *planstate, TupleDesc tupDesc)
 
void ExecAssignResultTypeFromTL (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 ExecAssignScanTypeFromOuterPlan (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:562
text * cstring_to_text(const char *s)
Definition: varlena.c:150
#define DatumGetPointer(X)
Definition: postgres.h:555

Definition at line 447 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 483 of file executor.h.

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 407 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 408 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 1235 of file execTuples.c.

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

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

1236 {
1237  TupOutputState *tstate;
1238 
1239  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
1240 
1241  tstate->slot = MakeSingleTupleTableSlot(tupdesc);
1242  tstate->dest = dest;
1243 
1244  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
1245 
1246  return tstate;
1247 }
TupleTableSlot * slot
Definition: executor.h:432
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
void * palloc(Size size)
Definition: mcxt.c:835
DestReceiver * dest
Definition: executor.h:433

◆ BuildTupleHashTable()

TupleHashTable BuildTupleHashTable ( int  numCols,
AttrNumber keyColIdx,
FmgrInfo eqfunctions,
FmgrInfo hashfunctions,
long  nbuckets,
Size  additionalsize,
MemoryContext  tablecxt,
MemoryContext  tempcxt,
bool  use_variable_hash_iv 
)

Definition at line 290 of file execGrouping.c.

References Assert, TupleHashTableData::cur_eq_funcs, TupleHashTableData::entrysize, TupleHashTableData::hash_iv, hash_uint32(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, MemoryContextAlloc(), Min, TupleHashTableData::numCols, ParallelWorkerNumber, TupleHashTableData::tab_eq_funcs, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and work_mem.

Referenced by build_hash_table(), and buildSubPlanHash().

296 {
297  TupleHashTable hashtable;
298  Size entrysize = sizeof(TupleHashEntryData) + additionalsize;
299 
300  Assert(nbuckets > 0);
301 
302  /* Limit initial table size request to not more than work_mem */
303  nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize));
304 
305  hashtable = (TupleHashTable)
306  MemoryContextAlloc(tablecxt, sizeof(TupleHashTableData));
307 
308  hashtable->numCols = numCols;
309  hashtable->keyColIdx = keyColIdx;
310  hashtable->tab_hash_funcs = hashfunctions;
311  hashtable->tab_eq_funcs = eqfunctions;
312  hashtable->tablecxt = tablecxt;
313  hashtable->tempcxt = tempcxt;
314  hashtable->entrysize = entrysize;
315  hashtable->tableslot = NULL; /* will be made on first lookup */
316  hashtable->inputslot = NULL;
317  hashtable->in_hash_funcs = NULL;
318  hashtable->cur_eq_funcs = NULL;
319 
320  /*
321  * If parallelism is in use, even if the master backend is performing the
322  * scan itself, we don't want to create the hashtable exactly the same way
323  * in all workers. As hashtables are iterated over in keyspace-order,
324  * doing so in all processes in the same way is likely to lead to
325  * "unbalanced" hashtables when the table size initially is
326  * underestimated.
327  */
328  if (use_variable_hash_iv)
330  else
331  hashtable->hash_iv = 0;
332 
333  hashtable->hashtab = tuplehash_create(tablecxt, nbuckets, hashtable);
334 
335  return hashtable;
336 }
TupleTableSlot * inputslot
Definition: execnodes.h:628
#define Min(x, y)
Definition: c.h:826
AttrNumber * keyColIdx
Definition: execnodes.h:620
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:621
FmgrInfo * in_hash_funcs
Definition: execnodes.h:629
struct TupleHashEntryData TupleHashEntryData
MemoryContext tablecxt
Definition: execnodes.h:623
struct TupleHashTableData * TupleHashTable
Definition: execnodes.h:598
int ParallelWorkerNumber
Definition: parallel.c:100
Datum hash_uint32(uint32 k)
Definition: hashfunc.c:853
int work_mem
Definition: globals.c:113
tuplehash_hash * hashtab
Definition: execnodes.h:618
#define Assert(condition)
Definition: c.h:680
TupleTableSlot * tableslot
Definition: execnodes.h:626
size_t Size
Definition: c.h:414
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
FmgrInfo * cur_eq_funcs
Definition: execnodes.h:630
MemoryContext tempcxt
Definition: execnodes.h:624
FmgrInfo * tab_eq_funcs
Definition: execnodes.h:622

◆ 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 540 of file execReplication.c.

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

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

541 {
542  PublicationActions *pubactions;
543 
544  /* We only need to do checks for UPDATE and DELETE. */
545  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
546  return;
547 
548  /* If relation has replica identity we are always good. */
549  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL ||
551  return;
552 
553  /*
554  * This is either UPDATE OR DELETE and there is no replica identity.
555  *
556  * Check if the table publishes UPDATES or DELETES.
557  */
558  pubactions = GetRelationPublicationActions(rel);
559  if (cmd == CMD_UPDATE && pubactions->pubupdate)
560  ereport(ERROR,
561  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
562  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
564  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
565  else if (cmd == CMD_DELETE && pubactions->pubdelete)
566  ereport(ERROR,
567  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
568  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
570  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
571 }
int errhint(const char *fmt,...)
Definition: elog.c:987
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4646
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:114
#define OidIsValid(objectId)
Definition: c.h:586
#define REPLICA_IDENTITY_FULL
Definition: pg_class.h:179
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:445
#define ereport(elevel, rest)
Definition: elog.h:122
struct PublicationActions * GetRelationPublicationActions(Relation relation)
Definition: relcache.c:5142
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ CheckSubscriptionRelkind()

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

Definition at line 580 of file execReplication.c.

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

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

582 {
583  /*
584  * We currently only support writing to regular tables.
585  */
586  if (relkind != RELKIND_RELATION)
587  ereport(ERROR,
588  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
589  errmsg("logical replication target relation \"%s.%s\" is not a table",
590  nspname, relname)));
591 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_RELATION
Definition: pg_class.h:160

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation 
)

Definition at line 1098 of file execMain.c.

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

Referenced by ExecInitModifyTable(), and ExecSetupPartitionTupleRouting().

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

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 81 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_junkFilter, EState::es_lastoid, EState::es_leaf_result_relations, 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_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(), ExecuteTruncate(), ExplainExecuteQuery(), get_actual_variable_range(), get_qual_for_range(), IndexBuildHeapRangeScan(), IndexCheckExclusion(), operator_predicate_proof(), plpgsql_create_econtext(), plpgsql_inline_handler(), standard_ExecutorStart(), tuplesort_begin_cluster(), unique_key_recheck(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().

82 {
83  EState *estate;
84  MemoryContext qcontext;
85  MemoryContext oldcontext;
86 
87  /*
88  * Create the per-query context for this Executor run.
89  */
91  "ExecutorState",
93 
94  /*
95  * Make the EState node within the per-query context. This way, we don't
96  * need a separate pfree() operation for it at shutdown.
97  */
98  oldcontext = MemoryContextSwitchTo(qcontext);
99 
100  estate = makeNode(EState);
101 
102  /*
103  * Initialize all fields of the Executor State structure
104  */
106  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
107  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
108  estate->es_range_table = NIL;
109  estate->es_plannedstmt = NULL;
110 
111  estate->es_junkFilter = NULL;
112 
113  estate->es_output_cid = (CommandId) 0;
114 
115  estate->es_result_relations = NULL;
116  estate->es_num_result_relations = 0;
117  estate->es_result_relation_info = NULL;
118 
119  estate->es_root_result_relations = NULL;
120  estate->es_num_root_result_relations = 0;
121 
122  estate->es_leaf_result_relations = NIL;
123 
124  estate->es_trig_target_relations = NIL;
125  estate->es_trig_tuple_slot = NULL;
126  estate->es_trig_oldtup_slot = NULL;
127  estate->es_trig_newtup_slot = NULL;
128 
129  estate->es_param_list_info = NULL;
130  estate->es_param_exec_vals = NULL;
131 
132  estate->es_queryEnv = NULL;
133 
134  estate->es_query_cxt = qcontext;
135 
136  estate->es_tupleTable = NIL;
137 
138  estate->es_rowMarks = NIL;
139 
140  estate->es_processed = 0;
141  estate->es_lastoid = InvalidOid;
142 
143  estate->es_top_eflags = 0;
144  estate->es_instrument = 0;
145  estate->es_finished = false;
146 
147  estate->es_exprcontexts = NIL;
148 
149  estate->es_subplanstates = NIL;
150 
151  estate->es_auxmodifytables = NIL;
152 
153  estate->es_per_tuple_exprcontext = NULL;
154 
155  estate->es_epqTuple = NULL;
156  estate->es_epqTupleSet = NULL;
157  estate->es_epqScanDone = NULL;
158  estate->es_sourceText = NULL;
159 
160  estate->es_use_parallel_mode = false;
161 
162  /*
163  * Return the executor state structure
164  */
165  MemoryContextSwitchTo(oldcontext);
166 
167  return estate;
168 }
#define NIL
Definition: pg_list.h:69
uint32 CommandId
Definition: c.h:469
HeapTuple * es_epqTuple
Definition: execnodes.h:517
JunkFilter * es_junkFilter
Definition: execnodes.h:446
CommandId es_output_cid
Definition: execnodes.h:449
TupleTableSlot * es_trig_newtup_slot
Definition: execnodes.h:473
Oid es_lastoid
Definition: execnodes.h:489
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlannedStmt * es_plannedstmt
Definition: execnodes.h:443
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:441
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:506
Snapshot es_snapshot
Definition: execnodes.h:440
List * es_range_table
Definition: execnodes.h:442
ScanDirection es_direction
Definition: execnodes.h:439
bool es_use_parallel_mode
Definition: execnodes.h:521
const char * es_sourceText
Definition: execnodes.h:444
ParamExecData * es_param_exec_vals
Definition: execnodes.h:477
MemoryContext es_query_cxt
Definition: execnodes.h:482
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
ResultRelInfo * es_result_relations
Definition: execnodes.h:452
TupleTableSlot * es_trig_oldtup_slot
Definition: execnodes.h:472
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
int es_instrument
Definition: execnodes.h:492
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:471
List * es_leaf_result_relations
Definition: execnodes.h:467
QueryEnvironment * es_queryEnv
Definition: execnodes.h:479
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
int es_num_root_result_relations
Definition: execnodes.h:464
#define InvalidSnapshot
Definition: snapshot.h:25
List * es_trig_target_relations
Definition: execnodes.h:470
List * es_tupleTable
Definition: execnodes.h:484
List * es_auxmodifytables
Definition: execnodes.h:499
int es_num_result_relations
Definition: execnodes.h:453
#define InvalidOid
Definition: postgres_ext.h:36
bool es_finished
Definition: execnodes.h:493
#define makeNode(_type_)
Definition: nodes.h:560
uint64 es_processed
Definition: execnodes.h:488
bool * es_epqTupleSet
Definition: execnodes.h:518
List * es_subplanstates
Definition: execnodes.h:497
List * es_rowMarks
Definition: execnodes.h:486
int es_top_eflags
Definition: execnodes.h:491
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:463
bool * es_epqScanDone
Definition: execnodes.h:519
ParamListInfo es_param_list_info
Definition: execnodes.h:476
List * es_exprcontexts
Definition: execnodes.h:495
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:454

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 226 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 ExecAssignExprContext(), ExecInitMergeJoin(), ExecInitSubPlan(), MakePerTupleExprContext(), and plpgsql_create_econtext().

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

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

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

299 {
300  ExprContext *econtext;
301 
302  /* Create the ExprContext node within the caller's memory context */
303  econtext = makeNode(ExprContext);
304 
305  /* Initialize fields of ExprContext */
306  econtext->ecxt_scantuple = NULL;
307  econtext->ecxt_innertuple = NULL;
308  econtext->ecxt_outertuple = NULL;
309 
311 
312  /*
313  * Create working memory for expression evaluation in this context.
314  */
315  econtext->ecxt_per_tuple_memory =
317  "ExprContext",
319 
320  econtext->ecxt_param_exec_vals = NULL;
321  econtext->ecxt_param_list_info = NULL;
322 
323  econtext->ecxt_aggvalues = NULL;
324  econtext->ecxt_aggnulls = NULL;
325 
326  econtext->caseValue_datum = (Datum) 0;
327  econtext->caseValue_isNull = true;
328 
329  econtext->domainValue_datum = (Datum) 0;
330  econtext->domainValue_isNull = true;
331 
332  econtext->ecxt_estate = NULL;
333 
334  econtext->ecxt_callbacks = NULL;
335 
336  return econtext;
337 }
Datum * ecxt_aggvalues
Definition: execnodes.h:224
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:214
Datum domainValue_datum
Definition: execnodes.h:232
Datum caseValue_datum
Definition: execnodes.h:228
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:239
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:209
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:217
struct EState * ecxt_estate
Definition: execnodes.h:236
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
bool domainValue_isNull
Definition: execnodes.h:233
bool * ecxt_aggnulls
Definition: execnodes.h:225
uintptr_t Datum
Definition: postgres.h:372
#define makeNode(_type_)
Definition: nodes.h:560
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:210
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:208
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:213
bool caseValue_isNull
Definition: execnodes.h:229
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:218

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 1281 of file execTuples.c.

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

Referenced by ExplainQuery().

1282 {
1283  Datum values[1];
1284  bool isnull[1] = {false};
1285 
1286  while (*txt)
1287  {
1288  const char *eol;
1289  int len;
1290 
1291  eol = strchr(txt, '\n');
1292  if (eol)
1293  {
1294  len = eol - txt;
1295  eol++;
1296  }
1297  else
1298  {
1299  len = strlen(txt);
1300  eol = txt + len;
1301  }
1302 
1303  values[0] = PointerGetDatum(cstring_to_text_with_len(txt, len));
1304  do_tup_output(tstate, values, isnull);
1305  pfree(DatumGetPointer(values[0]));
1306  txt = eol;
1307  }
1308 }
#define PointerGetDatum(X)
Definition: postgres.h:562
void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
Definition: execTuples.c:1253
void pfree(void *pointer)
Definition: mcxt.c:936
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:162
uintptr_t Datum
Definition: postgres.h:372
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164

◆ do_tup_output()

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

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

1254 {
1255  TupleTableSlot *slot = tstate->slot;
1256  int natts = slot->tts_tupleDescriptor->natts;
1257 
1258  /* make sure the slot is clear */
1259  ExecClearTuple(slot);
1260 
1261  /* insert data */
1262  memcpy(slot->tts_values, values, natts * sizeof(Datum));
1263  memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
1264 
1265  /* mark slot as containing a virtual tuple */
1266  ExecStoreVirtualTuple(slot);
1267 
1268  /* send the tuple to the receiver */
1269  (void) tstate->dest->receiveSlot(slot, tstate->dest);
1270 
1271  /* clean up */
1272  ExecClearTuple(slot);
1273 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
Datum * tts_values
Definition: tuptable.h:125
TupleTableSlot * slot
Definition: executor.h:432
int natts
Definition: tupdesc.h:79
bool * tts_isnull
Definition: tuptable.h:126
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
uintptr_t Datum
Definition: postgres.h:372
static Datum values[MAXATTR]
Definition: bootstrap.c:164
DestReceiver * dest
Definition: executor.h:433
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 1311 of file execTuples.c.

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

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

1312 {
1313  tstate->dest->rShutdown(tstate->dest);
1314  /* note that destroying the dest is not ours to do */
1316  pfree(tstate);
1317 }
TupleTableSlot * slot
Definition: executor.h:432
void pfree(void *pointer)
Definition: mcxt.c:936
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
DestReceiver * dest
Definition: executor.h:433

◆ EvalPlanQual()

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

Definition at line 2493 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate,
EState parentestate 
)

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

3031 {
3032  EState *estate = epqstate->estate;
3033 
3034  if (estate == NULL)
3035  {
3036  /* First time through, so create a child EState */
3037  EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
3038  }
3039  else
3040  {
3041  /*
3042  * We already have a suitable child EPQ tree, so just reset it.
3043  */
3044  int rtsize = list_length(parentestate->es_range_table);
3045  PlanState *planstate = epqstate->planstate;
3046 
3047  MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
3048 
3049  /* Recopy current values of parent parameters */
3050  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
3051  {
3052  int i;
3053 
3054  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
3055 
3056  while (--i >= 0)
3057  {
3058  /* copy value if any, but not execPlan link */
3059  estate->es_param_exec_vals[i].value =
3060  parentestate->es_param_exec_vals[i].value;
3061  estate->es_param_exec_vals[i].isnull =
3062  parentestate->es_param_exec_vals[i].isnull;
3063  }
3064  }
3065 
3066  /*
3067  * Mark child plan tree as needing rescan at all scan nodes. The
3068  * first ExecProcNode will take care of actually doing the rescan.
3069  */
3070  planstate->chgParam = bms_add_member(planstate->chgParam,
3071  epqstate->epqParam);
3072  }
3073 }
List * paramExecTypes
Definition: plannodes.h:92
#define NIL
Definition: pg_list.h:69
PlannedStmt * es_plannedstmt
Definition: execnodes.h:443
#define MemSet(start, val, len)
Definition: c.h:877
List * es_range_table
Definition: execnodes.h:442
PlanState * planstate
Definition: execnodes.h:926
ParamExecData * es_param_exec_vals
Definition: execnodes.h:477
bool isnull
Definition: params.h:149
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
Definition: execMain.c:3082
Bitmapset * chgParam
Definition: execnodes.h:886
Plan * plan
Definition: execnodes.h:928
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:742
int i
bool * es_epqScanDone
Definition: execnodes.h:519
Datum value
Definition: params.h:148
int epqParam
Definition: execnodes.h:930
EState * estate
Definition: execnodes.h:925

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

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

3224 {
3225  EState *estate = epqstate->estate;
3226  MemoryContext oldcontext;
3227  ListCell *l;
3228 
3229  if (estate == NULL)
3230  return; /* idle, so nothing to do */
3231 
3232  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3233 
3234  ExecEndNode(epqstate->planstate);
3235 
3236  foreach(l, estate->es_subplanstates)
3237  {
3238  PlanState *subplanstate = (PlanState *) lfirst(l);
3239 
3240  ExecEndNode(subplanstate);
3241  }
3242 
3243  /* throw away the per-estate tuple table */
3244  ExecResetTupleTable(estate->es_tupleTable, false);
3245 
3246  /* close any trigger target relations attached to this EState */
3247  ExecCleanUpTriggerState(estate);
3248 
3249  MemoryContextSwitchTo(oldcontext);
3250 
3251  FreeExecutorState(estate);
3252 
3253  /* Mark EPQState idle */
3254  epqstate->estate = NULL;
3255  epqstate->planstate = NULL;
3256  epqstate->origslot = NULL;
3257 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:926
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
MemoryContext es_query_cxt
Definition: execnodes.h:482
TupleTableSlot * origslot
Definition: execnodes.h:927
List * es_tupleTable
Definition: execnodes.h:484
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:156
#define lfirst(lc)
Definition: pg_list.h:106
List * es_subplanstates
Definition: execnodes.h:497
void ExecCleanUpTriggerState(EState *estate)
Definition: execMain.c:1466
EState * estate
Definition: execnodes.h:925

◆ EvalPlanQualFetch()

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

Definition at line 2580 of file execMain.c.

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

Referenced by EvalPlanQual(), and ExecLockRows().

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

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

Referenced by EvalPlanQual(), and ExecLockRows().

2880 {
2881  ListCell *l;
2882 
2883  Assert(epqstate->origslot != NULL);
2884 
2885  foreach(l, epqstate->arowMarks)
2886  {
2887  ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
2888  ExecRowMark *erm = aerm->rowmark;
2889  Datum datum;
2890  bool isNull;
2891  HeapTupleData tuple;
2892 
2894  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2895 
2896  /* clear any leftover test tuple for this rel */
2897  EvalPlanQualSetTuple(epqstate, erm->rti, NULL);
2898 
2899  /* if child rel, must check whether it produced this row */
2900  if (erm->rti != erm->prti)
2901  {
2902  Oid tableoid;
2903 
2904  datum = ExecGetJunkAttribute(epqstate->origslot,
2905  aerm->toidAttNo,
2906  &isNull);
2907  /* non-locked rels could be on the inside of outer joins */
2908  if (isNull)
2909  continue;
2910  tableoid = DatumGetObjectId(datum);
2911 
2912  Assert(OidIsValid(erm->relid));
2913  if (tableoid != erm->relid)
2914  {
2915  /* this child is inactive right now */
2916  continue;
2917  }
2918  }
2919 
2920  if (erm->markType == ROW_MARK_REFERENCE)
2921  {
2922  HeapTuple copyTuple;
2923 
2924  Assert(erm->relation != NULL);
2925 
2926  /* fetch the tuple's ctid */
2927  datum = ExecGetJunkAttribute(epqstate->origslot,
2928  aerm->ctidAttNo,
2929  &isNull);
2930  /* non-locked rels could be on the inside of outer joins */
2931  if (isNull)
2932  continue;
2933 
2934  /* fetch requests on foreign tables must be passed to their FDW */
2935  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2936  {
2937  FdwRoutine *fdwroutine;
2938  bool updated = false;
2939 
2940  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2941  /* this should have been checked already, but let's be safe */
2942  if (fdwroutine->RefetchForeignRow == NULL)
2943  ereport(ERROR,
2944  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2945  errmsg("cannot lock rows in foreign table \"%s\"",
2947  copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate,
2948  erm,
2949  datum,
2950  &updated);
2951  if (copyTuple == NULL)
2952  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2953 
2954  /*
2955  * Ideally we'd insist on updated == false here, but that
2956  * assumes that FDWs can track that exactly, which they might
2957  * not be able to. So just ignore the flag.
2958  */
2959  }
2960  else
2961  {
2962  /* ordinary table, fetch the tuple */
2963  Buffer buffer;
2964 
2965  tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
2966  if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
2967  false, NULL))
2968  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2969 
2970  /* successful, copy tuple */
2971  copyTuple = heap_copytuple(&tuple);
2972  ReleaseBuffer(buffer);
2973  }
2974 
2975  /* store tuple */
2976  EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
2977  }
2978  else
2979  {
2980  HeapTupleHeader td;
2981 
2982  Assert(erm->markType == ROW_MARK_COPY);
2983 
2984  /* fetch the whole-row Var for the relation */
2985  datum = ExecGetJunkAttribute(epqstate->origslot,
2986  aerm->wholeAttNo,
2987  &isNull);
2988  /* non-locked rels could be on the inside of outer joins */
2989  if (isNull)
2990  continue;
2991  td = DatumGetHeapTupleHeader(datum);
2992 
2993  /* build a temporary HeapTuple control structure */
2995  tuple.t_data = td;
2996  /* relation might be a foreign table, if so provide tableoid */
2997  tuple.t_tableOid = erm->relid;
2998  /* also copy t_ctid in case there's valid data there */
2999  tuple.t_self = td->t_ctid;
3000 
3001  /* copy and store tuple */
3002  EvalPlanQualSetTuple(epqstate, erm->rti,
3003  heap_copytuple(&tuple));
3004  }
3005  }
3006 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
void EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
Definition: execMain.c:2844
Relation relation
Definition: execnodes.h:547
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1876
#define DatumGetObjectId(X)
Definition: postgres.h:506
int errcode(int sqlerrcode)
Definition: elog.c:575
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:975
ItemPointerData * ItemPointer
Definition: itemptr.h:49
ExecRowMark * rowmark
Definition: execnodes.h:574
HeapTupleHeader t_data
Definition: htup.h:67
#define ERROR
Definition: elog.h:43
ItemPointerData t_ctid
Definition: htup_details.h:155
ItemPointerData t_self
Definition: htup.h:65
List * arowMarks
Definition: execnodes.h:929
uint32 t_len
Definition: htup.h:64
Index rti
Definition: execnodes.h:549
AttrNumber wholeAttNo
Definition: execnodes.h:577
Index prti
Definition: execnodes.h:550
#define RelationGetRelationName(relation)
Definition: rel.h:445
Oid t_tableOid
Definition: htup.h:66
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
TupleTableSlot * origslot
Definition: execnodes.h:927
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define SnapshotAny
Definition: tqual.h:28
#define Assert(condition)
Definition: c.h:680
#define lfirst(lc)
Definition: pg_list.h:106
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
RowMarkType markType
Definition: execnodes.h:552
AttrNumber toidAttNo
Definition: execnodes.h:576
#define DatumGetPointer(X)
Definition: postgres.h:555
int errmsg(const char *fmt,...)
Definition: elog.c:797
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: execJunk.c:248
#define elog
Definition: elog.h:219
EState * estate
Definition: execnodes.h:925
int Buffer
Definition: buf.h:23
AttrNumber ctidAttNo
Definition: execnodes.h:575
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:215
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:444

◆ EvalPlanQualGetTuple()

HeapTuple EvalPlanQualGetTuple ( EPQState epqstate,
Index  rti 
)

Definition at line 2864 of file execMain.c.

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

2865 {
2866  EState *estate = epqstate->estate;
2867 
2868  Assert(rti > 0);
2869 
2870  return estate->es_epqTuple[rti - 1];
2871 }
HeapTuple * es_epqTuple
Definition: execnodes.h:517
#define Assert(condition)
Definition: c.h:680
EState * estate
Definition: execnodes.h:925

◆ EvalPlanQualInit()

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

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

2811 {
2812  /* Mark the EPQ state inactive */
2813  epqstate->estate = NULL;
2814  epqstate->planstate = NULL;
2815  epqstate->origslot = NULL;
2816  /* ... and remember data that EvalPlanQualBegin will need */
2817  epqstate->plan = subplan;
2818  epqstate->arowMarks = auxrowmarks;
2819  epqstate->epqParam = epqParam;
2820 }
PlanState * planstate
Definition: execnodes.h:926
List * arowMarks
Definition: execnodes.h:929
TupleTableSlot * origslot
Definition: execnodes.h:927
Plan * plan
Definition: execnodes.h:928
int epqParam
Definition: execnodes.h:930
EState * estate
Definition: execnodes.h:925

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 3014 of file execMain.c.

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

Referenced by EvalPlanQual(), and ExecLockRows().

3015 {
3016  MemoryContext oldcontext;
3017  TupleTableSlot *slot;
3018 
3019  oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
3020  slot = ExecProcNode(epqstate->planstate);
3021  MemoryContextSwitchTo(oldcontext);
3022 
3023  return slot;
3024 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlanState * planstate
Definition: execnodes.h:926
MemoryContext es_query_cxt
Definition: execnodes.h:482
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:240
EState * estate
Definition: execnodes.h:925

◆ EvalPlanQualSetPlan()

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

Definition at line 2828 of file execMain.c.

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

Referenced by ExecInitModifyTable(), and ExecModifyTable().

2829 {
2830  /* If we have a live EPQ query, shut it down */
2831  EvalPlanQualEnd(epqstate);
2832  /* And set/change the plan pointer */
2833  epqstate->plan = subplan;
2834  /* The rowmarks depend on the plan, too */
2835  epqstate->arowMarks = auxrowmarks;
2836 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3223
List * arowMarks
Definition: execnodes.h:929
Plan * plan
Definition: execnodes.h:928

◆ EvalPlanQualSetTuple()

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

Definition at line 2844 of file execMain.c.

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

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

2845 {
2846  EState *estate = epqstate->estate;
2847 
2848  Assert(rti > 0);
2849 
2850  /*
2851  * free old test tuple, if any, and store new tuple where relation's scan
2852  * node will see it
2853  */
2854  if (estate->es_epqTuple[rti - 1] != NULL)
2855  heap_freetuple(estate->es_epqTuple[rti - 1]);
2856  estate->es_epqTuple[rti - 1] = tuple;
2857  estate->es_epqTupleSet[rti - 1] = true;
2858 }
HeapTuple * es_epqTuple
Definition: execnodes.h:517
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define Assert(condition)
Definition: c.h:680
bool * es_epqTupleSet
Definition: execnodes.h:518
EState * estate
Definition: execnodes.h:925

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

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

497 {
498  planstate->ps_ProjInfo =
500  planstate->ps_ExprContext,
501  planstate->ps_ResultTupleSlot,
502  planstate,
503  inputDesc);
504 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:893
ExprContext * ps_ExprContext
Definition: execnodes.h:892
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:891
Plan * plan
Definition: execnodes.h:858
List * targetlist
Definition: plannodes.h:144
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:348

◆ ExecAssignResultType()

void ExecAssignResultType ( PlanState planstate,
TupleDesc  tupDesc 
)

Definition at line 436 of file execUtils.c.

References ExecSetSlotDescriptor(), and PlanState::ps_ResultTupleSlot.

Referenced by ExecAssignResultTypeFromTL().

437 {
438  TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
439 
440  ExecSetSlotDescriptor(slot, tupDesc);
441 }
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:891
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247

◆ ExecAssignResultTypeFromTL()

void ExecAssignResultTypeFromTL ( PlanState planstate)

Definition at line 448 of file execUtils.c.

References ExecAssignResultType(), ExecContextForcesOids(), ExecTypeFromTL(), PlanState::plan, and Plan::targetlist.

Referenced by ExecInitAgg(), ExecInitAppend(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitCustomScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGather(), ExecInitGatherMerge(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNamedTuplestoreScan(), ExecInitNestLoop(), ExecInitProjectSet(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSampleScan(), ExecInitSeqScan(), ExecInitSetOp(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitTableFuncScan(), ExecInitTidScan(), ExecInitUnique(), ExecInitValuesScan(), ExecInitWindowAgg(), and ExecInitWorkTableScan().

449 {
450  bool hasoid;
451  TupleDesc tupDesc;
452 
453  if (ExecContextForcesOids(planstate, &hasoid))
454  {
455  /* context forces OID choice; hasoid is now set correctly */
456  }
457  else
458  {
459  /* given free choice, don't leave space for OIDs in result tuples */
460  hasoid = false;
461  }
462 
463  /*
464  * ExecTypeFromTL needs the parse-time representation of the tlist, not a
465  * list of ExprStates. This is good because some plan nodes don't bother
466  * to set up planstate->targetlist ...
467  */
468  tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
469  ExecAssignResultType(planstate, tupDesc);
470 }
void ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
Definition: execUtils.c:436
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
Plan * plan
Definition: execnodes.h:858
List * targetlist
Definition: plannodes.h:144
bool ExecContextForcesOids(PlanState *planstate, bool *hasoids)
Definition: execMain.c:1513

◆ 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:1117
void ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc, Index varno)
Definition: execUtils.c:515
PlanState ps
Definition: execnodes.h:1114
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121

◆ ExecAssignScanType()

◆ ExecAssignScanTypeFromOuterPlan()

void ExecAssignScanTypeFromOuterPlan ( ScanState scanstate)

Definition at line 639 of file execUtils.c.

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

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

640 {
642  TupleDesc tupDesc;
643 
644  outerPlan = outerPlanState(scanstate);
645  tupDesc = ExecGetResultType(outerPlan);
646 
647  ExecAssignScanType(scanstate, tupDesc);
648 }
#define outerPlanState(node)
Definition: execnodes.h:904
#define outerPlan(node)
Definition: plannodes.h:174
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:477
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:627

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

2423 {
2424  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2425  char resname[32];
2426 
2427  aerm->rowmark = erm;
2428 
2429  /* Look up the resjunk columns associated with this rowmark */
2430  if (erm->markType != ROW_MARK_COPY)
2431  {
2432  /* need ctid for all methods other than COPY */
2433  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2434  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2435  resname);
2436  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2437  elog(ERROR, "could not find junk %s column", resname);
2438  }
2439  else
2440  {
2441  /* need wholerow if COPY */
2442  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2443  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2444  resname);
2445  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2446  elog(ERROR, "could not find junk %s column", resname);
2447  }
2448 
2449  /* if child rel, need tableoid */
2450  if (erm->rti != erm->prti)
2451  {
2452  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2453  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2454  resname);
2455  if (!AttributeNumberIsValid(aerm->toidAttNo))
2456  elog(ERROR, "could not find junk %s column", resname);
2457  }
2458 
2459  return aerm;
2460 }
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:574
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:549
AttrNumber wholeAttNo
Definition: execnodes.h:577
Index prti
Definition: execnodes.h:550
Index rowmarkId
Definition: execnodes.h:551
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
void * palloc0(Size size)
Definition: mcxt.c:864
RowMarkType markType
Definition: execnodes.h:552
AttrNumber toidAttNo
Definition: execnodes.h:576
#define elog
Definition: elog.h:219
AttrNumber ctidAttNo
Definition: execnodes.h:575

◆ ExecBuildProjectionInfo()

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

Definition at line 348 of file execExpr.c.

References ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, 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(), ExecInitSubPlan(), and ExecProcNode().

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext context 
)

Definition at line 594 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(), ExecQual(), ExecRelCheck(), and validateCheckConstraint().

595 {
596  Datum ret;
597  bool isnull;
598 
599  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
600  if (state == NULL)
601  return true;
602 
603  /* verify that expression was not compiled using ExecInitQual */
604  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
605 
606  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
607 
608  if (isnull)
609  return true;
610 
611  return DatumGetBool(ret);
612 }
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:298
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:55
#define DatumGetBool(X)
Definition: postgres.h:399
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:680
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:1774
int ri_NumIndices
Definition: execnodes.h:368
#define NIL
Definition: pg_list.h:69
Relation ri_RelationDesc
Definition: execnodes.h:365
List * ii_Predicate
Definition: execnodes.h:149
ExprState * ii_PredicateState
Definition: execnodes.h:150
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:363
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:474
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5267
Form_pg_index rd_index
Definition: rel.h:159
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:445
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:515
bool ii_ReadyForInserts
Definition: execnodes.h:158
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
bool ii_Unique
Definition: execnodes.h:157
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define INDEX_MAX_KEYS
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:208
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
Oid * ii_ExclusionOps
Definition: execnodes.h:151
int errmsg(const char *fmt,...)
Definition: elog.c:797
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:374
int i
#define elog
Definition: elog.h:219
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:371
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:454

◆ ExecCheckRTPerms()

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

Definition at line 568 of file execMain.c.

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

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

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1096 of file execUtils.c.

References lfirst_node, and TargetEntry::resjunk.

Referenced by check_sql_fn_retval(), and ExecTypeFromTLInternal().

1097 {
1098  int len = 0;
1099  ListCell *tl;
1100 
1101  foreach(tl, targetlist)
1102  {
1103  TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1104 
1105  if (!curTle->resjunk)
1106  len++;
1107  }
1108  return len;
1109 }
bool resjunk
Definition: primnodes.h:1382
#define lfirst_node(type, lc)
Definition: pg_list.h:109

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList,
bool  hasoid 
)

Definition at line 900 of file execTuples.c.

References ExecTypeFromTLInternal().

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

901 {
902  return ExecTypeFromTLInternal(targetList, hasoid, true);
903 }
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk)
Definition: execTuples.c:906

◆ ExecCleanUpTriggerState()

void ExecCleanUpTriggerState ( EState estate)

Definition at line 1466 of file execMain.c.

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

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

1467 {
1468  ListCell *l;
1469 
1470  foreach(l, estate->es_trig_target_relations)
1471  {
1472  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1473 
1474  /* Close indices and then the relation itself */
1475  ExecCloseIndices(resultRelInfo);
1476  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1477  }
1478 }
Relation ri_RelationDesc
Definition: execnodes.h:365
#define heap_close(r, l)
Definition: heapam.h:97
#define NoLock
Definition: lockdefs.h:34
List * es_trig_target_relations
Definition: execnodes.h:470
#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:368
#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:371

◆ ExecCloseScanRelation()

void ExecCloseScanRelation ( Relation  scanrel)

Definition at line 748 of file execUtils.c.

References heap_close, and NoLock.

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

749 {
750  heap_close(scanrel, NoLock);
751 }
#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 515 of file execUtils.c.

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

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

517 {
518  if (tlist_matches_tupdesc(planstate,
519  planstate->plan->targetlist,
520  varno,
521  inputDesc))
522  planstate->ps_ProjInfo = NULL;
523  else
524  ExecAssignProjectionInfo(planstate, inputDesc);
525 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:893
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:495
Plan * plan
Definition: execnodes.h:858
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
Definition: execUtils.c:528
List * targetlist
Definition: plannodes.h:144

◆ ExecConstraints()

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

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

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

◆ ExecContextForcesOids()

bool ExecContextForcesOids ( PlanState planstate,
bool hasoids 
)

Definition at line 1513 of file execMain.c.

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

Referenced by ExecAssignResultTypeFromTL(), ExecInitGather(), ExecInitGatherMerge(), and tlist_matches_tupdesc().

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

◆ execCurrentOf()

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

Definition at line 41 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(), ItemPointerIsValid, lfirst, ExecRowMark::markType, PG_USED_FOR_ASSERTS_ONLY, QueryDesc::planstate, PORTAL_ONE_SELECT, PortalIsValid, PortalData::queryDesc, ExecRowMark::relid, RowMarkRequiresRowShareLock, search_plan_tree(), SelfItemPointerAttributeNumber, slot_getattr(), ScanState::ss_ScanTupleSlot, PortalData::strategy, TableOidAttributeNumber, and TupIsNull.

Referenced by TidListEval().

45 {
46  char *cursor_name;
47  char *table_name;
48  Portal portal;
49  QueryDesc *queryDesc;
50 
51  /* Get the cursor name --- may have to look up a parameter reference */
52  if (cexpr->cursor_name)
53  cursor_name = cexpr->cursor_name;
54  else
55  cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param);
56 
57  /* Fetch table name for possible use in error messages */
58  table_name = get_rel_name(table_oid);
59  if (table_name == NULL)
60  elog(ERROR, "cache lookup failed for relation %u", table_oid);
61 
62  /* Find the cursor's portal */
63  portal = GetPortalByName(cursor_name);
64  if (!PortalIsValid(portal))
65  ereport(ERROR,
66  (errcode(ERRCODE_UNDEFINED_CURSOR),
67  errmsg("cursor \"%s\" does not exist", cursor_name)));
68 
69  /*
70  * We have to watch out for non-SELECT queries as well as held cursors,
71  * both of which may have null queryDesc.
72  */
73  if (portal->strategy != PORTAL_ONE_SELECT)
74  ereport(ERROR,
75  (errcode(ERRCODE_INVALID_CURSOR_STATE),
76  errmsg("cursor \"%s\" is not a SELECT query",
77  cursor_name)));
78  queryDesc = portal->queryDesc;
79  if (queryDesc == NULL || queryDesc->estate == NULL)
80  ereport(ERROR,
81  (errcode(ERRCODE_INVALID_CURSOR_STATE),
82  errmsg("cursor \"%s\" is held from a previous transaction",
83  cursor_name)));
84 
85  /*
86  * We have two different strategies depending on whether the cursor uses
87  * FOR UPDATE/SHARE or not. The reason for supporting both is that the
88  * FOR UPDATE code is able to identify a target table in many cases where
89  * the other code can't, while the non-FOR-UPDATE case allows use of WHERE
90  * CURRENT OF with an insensitive cursor.
91  */
92  if (queryDesc->estate->es_rowMarks)
93  {
94  ExecRowMark *erm;
95  ListCell *lc;
96 
97  /*
98  * Here, the query must have exactly one FOR UPDATE/SHARE reference to
99  * the target table, and we dig the ctid info out of that.
100  */
101  erm = NULL;
102  foreach(lc, queryDesc->estate->es_rowMarks)
103  {
104  ExecRowMark *thiserm = (ExecRowMark *) lfirst(lc);
105 
106  if (!RowMarkRequiresRowShareLock(thiserm->markType))
107  continue; /* ignore non-FOR UPDATE/SHARE items */
108 
109  if (thiserm->relid == table_oid)
110  {
111  if (erm)
112  ereport(ERROR,
113  (errcode(ERRCODE_INVALID_CURSOR_STATE),
114  errmsg("cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\"",
115  cursor_name, table_name)));
116  erm = thiserm;
117  }
118  }
119 
120  if (erm == NULL)
121  ereport(ERROR,
122  (errcode(ERRCODE_INVALID_CURSOR_STATE),
123  errmsg("cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\"",
124  cursor_name, table_name)));
125 
126  /*
127  * The cursor must have a current result row: per the SQL spec, it's
128  * an error if not.
129  */
130  if (portal->atStart || portal->atEnd)
131  ereport(ERROR,
132  (errcode(ERRCODE_INVALID_CURSOR_STATE),
133  errmsg("cursor \"%s\" is not positioned on a row",
134  cursor_name)));
135 
136  /* Return the currently scanned TID, if there is one */
137  if (ItemPointerIsValid(&(erm->curCtid)))
138  {
139  *current_tid = erm->curCtid;
140  return true;
141  }
142 
143  /*
144  * This table didn't produce the cursor's current row; some other
145  * inheritance child of the same parent must have. Signal caller to
146  * do nothing on this table.
147  */
148  return false;
149  }
150  else
151  {
152  ScanState *scanstate;
153  bool lisnull;
154  Oid tuple_tableoid PG_USED_FOR_ASSERTS_ONLY;
155  ItemPointer tuple_tid;
156 
157  /*
158  * Without FOR UPDATE, we dig through the cursor's plan to find the
159  * scan node. Fail if it's not there or buried underneath
160  * aggregation.
161  */
162  scanstate = search_plan_tree(queryDesc->planstate, table_oid);
163  if (!scanstate)
164  ereport(ERROR,
165  (errcode(ERRCODE_INVALID_CURSOR_STATE),
166  errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
167  cursor_name, table_name)));
168 
169  /*
170  * The cursor must have a current result row: per the SQL spec, it's
171  * an error if not. We test this at the top level, rather than at the
172  * scan node level, because in inheritance cases any one table scan
173  * could easily not be on a row. We want to return false, not raise
174  * error, if the passed-in table OID is for one of the inactive scans.
175  */
176  if (portal->atStart || portal->atEnd)
177  ereport(ERROR,
178  (errcode(ERRCODE_INVALID_CURSOR_STATE),
179  errmsg("cursor \"%s\" is not positioned on a row",
180  cursor_name)));
181 
182  /* Now OK to return false if we found an inactive scan */
183  if (TupIsNull(scanstate->ss_ScanTupleSlot))
184  return false;
185 
186  /* Use slot_getattr to catch any possible mistakes */
187  tuple_tableoid =
190  &lisnull));
191  Assert(!lisnull);
192  tuple_tid = (ItemPointer)
195  &lisnull));
196  Assert(!lisnull);
197 
198  Assert(tuple_tableoid == table_oid);
199 
200  *current_tid = *tuple_tid;
201 
202  return true;
203  }
204 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
bool atEnd
Definition: portal.h:187
EState * estate
Definition: execdesc.h:48
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
#define DatumGetObjectId(X)
Definition: postgres.h:506
int errcode(int sqlerrcode)
Definition: elog.c:575
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1117
unsigned int Oid
Definition: postgres_ext.h:31
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:975
ItemPointerData * ItemPointer
Definition: itemptr.h:49
ItemPointerData curCtid
Definition: execnodes.h:556
#define ERROR
Definition: elog.h:43
PlanState * planstate
Definition: execdesc.h:49
#define TupIsNull(slot)
Definition: tuptable.h:138
#define TableOidAttributeNumber
Definition: sysattr.h:27
char * cursor_name
Definition: primnodes.h:1285
PortalStrategy strategy
Definition: portal.h:143
#define ereport(elevel, rest)
Definition: elog.h:122
QueryDesc * queryDesc
Definition: portal.h:152
#define PortalIsValid(p)
Definition: portal.h:199
static ScanState * search_plan_tree(PlanState *node, Oid table_oid)
Definition: execCurrent.c:257
#define Assert(condition)
Definition: c.h:680
#define lfirst(lc)
Definition: pg_list.h:106
RowMarkType markType
Definition: execnodes.h:552
List * es_rowMarks
Definition: execnodes.h:486
#define DatumGetPointer(X)
Definition: postgres.h:555
bool atStart
Definition: portal.h:186
int errmsg(const char *fmt,...)
Definition: elog.c:797
static char * fetch_cursor_param_value(ExprContext *econtext, int paramId)
Definition: execCurrent.c:212
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1142
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
#define elog
Definition: elog.h:219
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:122
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1745

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

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

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

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

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

Definition at line 298 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(), recompute_limits(), tablesample_init(), TidListEval(), and validateDomainConstraint().

301 {
302  Datum retDatum;
303  MemoryContext oldContext;
304 
305  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
306  retDatum = state->evalfunc(state, econtext, isNull);
307  MemoryContextSwitchTo(oldContext);
308  return retDatum;
309 }
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:214
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprStateEvalFunc evalfunc
Definition: execnodes.h:84
uintptr_t Datum
Definition: postgres.h:372

◆ 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:345
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * jf_resultSlot
Definition: execnodes.h:346
Datum * tts_values
Definition: tuptable.h:125
int natts
Definition: tupdesc.h:79
bool * tts_isnull
Definition: tuptable.h:126
TupleDesc jf_cleanTupType
Definition: execnodes.h:344
void slot_getallattrs(TupleTableSlot *slot)
Definition: heaptuple.c:1238
uintptr_t Datum
Definition: postgres.h:372
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int i
int16 AttrNumber
Definition: attnum.h:21
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488

◆ 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:343

◆ 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 ExecBuildAuxRowMark(), ExecFindJunkAttribute(), and postgresBeginForeignModify().

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:1377
bool resjunk
Definition: primnodes.h:1382
AttrNumber resno
Definition: primnodes.h:1376
#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 2398 of file execMain.c.

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

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

2399 {
2400  ListCell *lc;
2401 
2402  foreach(lc, estate->es_rowMarks)
2403  {
2404  ExecRowMark *erm = (ExecRowMark *) lfirst(lc);
2405 
2406  if (erm->rti == rti)
2407  return erm;
2408  }
2409  if (!missing_ok)
2410  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2411  return NULL;
2412 }
#define ERROR
Definition: elog.h:43
Index rti
Definition: execnodes.h:549
#define lfirst(lc)
Definition: pg_list.h:106
List * es_rowMarks
Definition: execnodes.h:486
#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:680
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1142

◆ ExecGetResultType()

◆ ExecGetTriggerResultRel()

ResultRelInfo* ExecGetTriggerResultRel ( EState estate,
Oid  relid 
)

Definition at line 1388 of file execMain.c.

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

Referenced by afterTriggerInvokeEvents().

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

◆ ExecInitCheck()

ExprState* ExecInitCheck ( List qual,
PlanState parent 
)

Definition at line 293 of file execExpr.c.

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

Referenced by ExecPrepareCheck(), and ExecProcNode().

294 {
295  /* short-circuit (here and in ExecCheck) for empty restriction list */
296  if (qual == NIL)
297  return NULL;
298 
299  Assert(IsA(qual, List));
300 
301  /*
302  * Just convert the implicit-AND list to an explicit AND (if there's more
303  * than one entry), and compile normally. Unlike ExecQual, we can't
304  * short-circuit on NULL results, so the regular AND behavior is needed.
305  */
306  return ExecInitExpr(make_ands_explicit(qual), parent);
307 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Expr * make_ands_explicit(List *andclauses)
Definition: clauses.c:370
#define Assert(condition)
Definition: c.h:680
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:118
Definition: pg_list.h:45

◆ ExecInitExpr()

ExprState* ExecInitExpr ( Expr node,
PlanState parent 
)

Definition at line 118 of file execExpr.c.

References EEOP_DONE, ExecInitExprRec(), ExecInitExprSlots(), ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprState::ext_params, makeNode, ExprEvalStep::opcode, ExprState::parent, ExprState::resnull, and ExprState::resvalue.

Referenced by ATRewriteTable(), BeginCopyFrom(), evaluate_expr(), ExecIndexBuildScanKeys(), ExecInitCheck(), ExecInitExprList(), ExecInitExprRec(), ExecInitHashJoin(), ExecInitLimit(), ExecInitProjectSet(), ExecInitSampleScan(), ExecInitSubPlan(), ExecInitTableFuncScan(), ExecInitTableFunctionResult(), ExecInitWindowAgg(), ExecPrepareExpr(), ExecProcNode(), get_cast_hashentry(), get_qual_for_range(), MJExamineQuals(), operator_predicate_proof(), prep_domain_constraints(), slot_fill_defaults(), and TidExprListCreate().

119 {
120  ExprState *state;
121  ExprEvalStep scratch;
122 
123  /* Special case: NULL expression produces a NULL ExprState pointer */
124  if (node == NULL)
125  return NULL;
126 
127  /* Initialize ExprState with empty step list */
128  state = makeNode(ExprState);
129  state->expr = node;
130  state->parent = parent;
131  state->ext_params = NULL;
132 
133  /* Insert EEOP_*_FETCHSOME steps as needed */
134  ExecInitExprSlots(state, (Node *) node);
135 
136  /* Compile the expression proper */
137  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
138 
139  /* Finally, append a DONE step */
140  scratch.opcode = EEOP_DONE;
141  ExprEvalPushStep(state, &scratch);
142 
143  ExecReadyExpr(state);
144 
145  return state;
146 }
struct PlanState * parent
Definition: execnodes.h:100
ParamListInfo ext_params
Definition: execnodes.h:101
Definition: nodes.h:512
bool resnull
Definition: execnodes.h:67
Expr * expr
Definition: execnodes.h:87
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2256
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:638
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2126
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:624
#define makeNode(_type_)
Definition: nodes.h:560
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:245
Datum resvalue
Definition: execnodes.h:68

◆ ExecInitExprList()

List* ExecInitExprList ( List nodes,
PlanState parent 
)

Definition at line 313 of file execExpr.c.

References ExecInitExpr(), lappend(), lfirst, and NIL.

Referenced by ExecInitAgg(), ExecInitExprRec(), ExecInitFunctionResultSet(), ExecInitIndexScan(), ExecInitSampleScan(), ExecInitSubPlan(), ExecInitTableFuncScan(), ExecInitTableFunctionResult(), ExecProcNode(), prepare_query_params(), and ValuesNext().

314 {
315  List *result = NIL;
316  ListCell *lc;
317 
318  foreach(lc, nodes)
319  {
320  Expr *e = lfirst(lc);
321 
322  result = lappend(result, ExecInitExpr(e, parent));
323  }
324 
325  return result;
326 }
#define NIL
Definition: pg_list.h:69
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
e
Definition: preproc-init.c:82
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:118
Definition: pg_list.h:45

◆ ExecInitExprWithParams()

ExprState* ExecInitExprWithParams ( Expr node,
ParamListInfo  ext_params 
)

Definition at line 155 of file execExpr.c.

References EEOP_DONE, ExecInitExprRec(), ExecInitExprSlots(), ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprState::ext_params, makeNode, ExprEvalStep::opcode, ExprState::parent, ExprState::resnull, and ExprState::resvalue.

Referenced by exec_eval_simple_expr(), and ExecProcNode().

156 {
157  ExprState *state;
158  ExprEvalStep scratch;
159 
160  /* Special case: NULL expression produces a NULL ExprState pointer */
161  if (node == NULL)
162  return NULL;
163 
164  /* Initialize ExprState with empty step list */
165  state = makeNode(ExprState);
166  state->expr = node;
167  state->parent = NULL;
168  state->ext_params = ext_params;
169 
170  /* Insert EEOP_*_FETCHSOME steps as needed */
171  ExecInitExprSlots(state, (Node *) node);
172 
173  /* Compile the expression proper */
174  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
175 
176  /* Finally, append a DONE step */
177  scratch.opcode = EEOP_DONE;
178  ExprEvalPushStep(state, &scratch);
179 
180  ExecReadyExpr(state);
181 
182  return state;
183 }
struct PlanState * parent
Definition: execnodes.h:100
ParamListInfo ext_params
Definition: execnodes.h:101
Definition: nodes.h:512
bool resnull
Definition: execnodes.h:67
Expr * expr
Definition: execnodes.h:87
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2256
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:638
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2126
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:624
#define makeNode(_type_)
Definition: nodes.h:560
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:245
Datum resvalue
Definition: execnodes.h:68

◆ ExecInitExtraTupleSlot()

◆ ExecInitFunctionResultSet()

SetExprState* ExecInitFunctionResultSet ( Expr expr,
ExprContext econtext,
PlanState parent 
)

Definition at line 424 of file execSRF.c.

References FuncExpr::args, OpExpr::args, SetExprState::args, Assert, ExprContext::ecxt_per_query_memory, elog, ERROR, ExecInitExprList(), SetExprState::expr, FmgrInfo::fn_oid, FmgrInfo::fn_retset, SetExprState::func, FuncExpr::funcid, SetExprState::funcReturnsSet, init_sexpr(), FuncExpr::inputcollid, OpExpr::inputcollid, InvalidOid, IsA, makeNode, nodeTag, and OpExpr::opfuncid.

Referenced by ExecInitProjectSet(), and ExecQual().

426 {
428 
429  state->funcReturnsSet = true;
430  state->expr = expr;
431  state->func.fn_oid = InvalidOid;
432 
433  /*
434  * Initialize metadata. The expression node could be either a FuncExpr or
435  * an OpExpr.
436  */
437  if (IsA(expr, FuncExpr))
438  {
439  FuncExpr *func = (FuncExpr *) expr;
440 
441  state->args = ExecInitExprList(func->args, parent);
442  init_sexpr(func->funcid, func->inputcollid, expr, state, parent,
443  econtext->ecxt_per_query_memory, true, true);
444  }
445  else if (IsA(expr, OpExpr))
446  {
447  OpExpr *op = (OpExpr *) expr;
448 
449  state->args = ExecInitExprList(op->args, parent);
450  init_sexpr(op->opfuncid, op->inputcollid, expr, state, parent,
451  econtext->ecxt_per_query_memory, true, true);
452  }
453  else
454  elog(ERROR, "unrecognized node type: %d",
455  (int) nodeTag(expr));
456 
457  /* shouldn't get here unless the selected function returns set */
458  Assert(state->func.fn_retset);
459 
460  return state;
461 }
FmgrInfo func
Definition: execnodes.h:715
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
List * args
Definition: primnodes.h:457
List * args
Definition: execnodes.h:701
static void init_sexpr(Oid foid, Oid input_collation, Expr *node, SetExprState *sexpr, PlanState *parent, MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF)
Definition: execSRF.c:676
bool fn_retset
Definition: fmgr.h:62
Oid funcid
Definition: primnodes.h:449
#define ERROR
Definition: elog.h:43