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

Go to the source code of this file.

Data Structures

struct  TupOutputState
 

Macros

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

Typedefs

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

Functions

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

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:600
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define DatumGetPointer(X)
Definition: postgres.h:593

Definition at line 504 of file executor.h.

Referenced by ExplainQuery(), and ShowGUCConfigOption().

◆ EvalPlanQualSetSlot

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

◆ EXEC_FLAG_BACKWARD

◆ EXEC_FLAG_EXPLAIN_ONLY

◆ EXEC_FLAG_MARK

◆ EXEC_FLAG_REWIND

◆ EXEC_FLAG_SKIP_TRIGGERS

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

◆ EXEC_FLAG_WITH_NO_DATA

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

Definition at line 61 of file executor.h.

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

◆ GetPerTupleExprContext

◆ GetPerTupleMemoryContext

◆ ResetExprContext

◆ ResetPerTupleExprContext

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

Definition at line 541 of file executor.h.

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 455 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 456 of file executor.h.

◆ ExecutorCheckPerms_hook_type

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

Definition at line 84 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 80 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 76 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 69 of file executor.h.

◆ ExecutorStart_hook_type

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

Definition at line 65 of file executor.h.

◆ TupOutputState

Function Documentation

◆ begin_tup_output_tupdesc()

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

Definition at line 2236 of file execTuples.c.

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

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

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

◆ BuildTupleHashTable()

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

Definition at line 253 of file execGrouping.c.

References BuildTupleHashTableExt().

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

◆ BuildTupleHashTableExt()

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

Definition at line 154 of file execGrouping.c.

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

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

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

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

References CEOUC_WAIT, and check_exclusion_or_unique_constraint().

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

892 {
893  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
894  values, isnull,
895  estate, newIndex,
896  CEOUC_WAIT, false, NULL);
897 }
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:667
static Datum values[MAXATTR]
Definition: bootstrap.c:166

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 568 of file execReplication.c.

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

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

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

◆ CheckSubscriptionRelkind()

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

Definition at line 608 of file execReplication.c.

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

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

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

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation 
)

Definition at line 992 of file execMain.c.

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

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

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

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 90 of file execUtils.c.

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

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

91 {
92  EState *estate;
93  MemoryContext qcontext;
94  MemoryContext oldcontext;
95 
96  /*
97  * Create the per-query context for this Executor run.
98  */
100  "ExecutorState",
102 
103  /*
104  * Make the EState node within the per-query context. This way, we don't
105  * need a separate pfree() operation for it at shutdown.
106  */
107  oldcontext = MemoryContextSwitchTo(qcontext);
108 
109  estate = makeNode(EState);
110 
111  /*
112  * Initialize all fields of the Executor State structure
113  */
115  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
116  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
117  estate->es_range_table = NIL;
118  estate->es_range_table_size = 0;
119  estate->es_relations = NULL;
120  estate->es_rowmarks = NULL;
121  estate->es_plannedstmt = NULL;
122 
123  estate->es_junkFilter = NULL;
124 
125  estate->es_output_cid = (CommandId) 0;
126 
127  estate->es_result_relations = NULL;
130  estate->es_trig_target_relations = NIL;
131 
132  estate->es_param_list_info = NULL;
133  estate->es_param_exec_vals = NULL;
134 
135  estate->es_queryEnv = NULL;
136 
137  estate->es_query_cxt = qcontext;
138 
139  estate->es_tupleTable = NIL;
140 
141  estate->es_processed = 0;
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_sourceText = NULL;
156 
157  estate->es_use_parallel_mode = false;
158 
159  estate->es_jit_flags = 0;
160  estate->es_jit = NULL;
161 
162  /*
163  * Return the executor state structure
164  */
165  MemoryContextSwitchTo(oldcontext);
166 
167  return estate;
168 }
#define NIL
Definition: pg_list.h:65
uint32 CommandId
Definition: c.h:601
JunkFilter * es_junkFilter
Definition: execnodes.h:567
#define AllocSetContextCreate
Definition: memutils.h:173
CommandId es_output_cid
Definition: execnodes.h:570
struct JitContext * es_jit
Definition: execnodes.h:644
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PlannedStmt * es_plannedstmt
Definition: execnodes.h:564
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:557
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:619
Snapshot es_snapshot
Definition: execnodes.h:556
List * es_range_table
Definition: execnodes.h:558
ScanDirection es_direction
Definition: execnodes.h:555
bool es_use_parallel_mode
Definition: execnodes.h:629
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:562
const char * es_sourceText
Definition: execnodes.h:565
ParamExecData * es_param_exec_vals
Definition: execnodes.h:593
MemoryContext es_query_cxt
Definition: execnodes.h:598
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
int es_jit_flags
Definition: execnodes.h:643
List * es_opened_result_relations
Definition: execnodes.h:576
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
int es_instrument
Definition: execnodes.h:605
ResultRelInfo ** es_result_relations
Definition: execnodes.h:573
QueryEnvironment * es_queryEnv
Definition: execnodes.h:595
#define InvalidSnapshot
Definition: snapshot.h:123
List * es_trig_target_relations
Definition: execnodes.h:589
List * es_tupleTable
Definition: execnodes.h:600
List * es_auxmodifytables
Definition: execnodes.h:612
List * es_tuple_routing_result_relations
Definition: execnodes.h:586
bool es_finished
Definition: execnodes.h:606
#define makeNode(_type_)
Definition: nodes.h:587
Relation * es_relations
Definition: execnodes.h:560
uint64 es_processed
Definition: execnodes.h:602
Index es_range_table_size
Definition: execnodes.h:559
List * es_subplanstates
Definition: execnodes.h:610
int es_top_eflags
Definition: execnodes.h:604
ParamListInfo es_param_list_info
Definition: execnodes.h:592
List * es_exprcontexts
Definition: execnodes.h:608

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 301 of file execUtils.c.

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

302 {
304 }
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: execUtils.c:231
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 352 of file execUtils.c.

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

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

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

◆ CreateWorkExprContext()

ExprContext* CreateWorkExprContext ( EState estate)

Definition at line 316 of file execUtils.c.

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

Referenced by ExecInitAgg().

317 {
318  Size minContextSize = ALLOCSET_DEFAULT_MINSIZE;
319  Size initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
320  Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
321 
322  /* choose the maxBlockSize to be no larger than 1/16 of work_mem */
323  while (16 * maxBlockSize > work_mem * 1024L)
324  maxBlockSize >>= 1;
325 
326  if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
327  maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
328 
329  return CreateExprContextInternal(estate, minContextSize,
330  initBlockSize, maxBlockSize);
331 }
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: execUtils.c:231
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:192
int work_mem
Definition: globals.c:124
size_t Size
Definition: c.h:540
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:193
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:194

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 2284 of file execTuples.c.

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

Referenced by ExplainQuery().

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

◆ do_tup_output()

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

Definition at line 2256 of file execTuples.c.

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

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

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

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 2314 of file execTuples.c.

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

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

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

◆ EvalPlanQual()

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

Definition at line 2359 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2622 of file execMain.c.

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

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

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2834 of file execMain.c.

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

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

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

◆ EvalPlanQualFetchRowMark()

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

Definition at line 2497 of file execMain.c.

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

Referenced by ExecScanFetch().

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

◆ EvalPlanQualInit()

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

Definition at line 2413 of file execMain.c.

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

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

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

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 2606 of file execMain.c.

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

Referenced by EvalPlanQual(), and ExecLockRows().

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

◆ EvalPlanQualSetPlan()

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

Definition at line 2452 of file execMain.c.

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

Referenced by ExecGetJunkAttribute(), and ExecInitModifyTable().

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

◆ EvalPlanQualSlot()

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

Definition at line 2469 of file execMain.c.

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

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

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

◆ exec_rt_fetch()

static RangeTblEntry* exec_rt_fetch ( Index  rti,
EState estate 
)
inlinestatic

Definition at line 570 of file executor.h.

References arg, attname, check_exclusion_constraint(), CheckCmdReplicaIdentity(), CheckSubscriptionRelkind(), EState::es_range_table, ExecCheckIndexConstraints(), ExecCleanTargetListLength(), ExecCloseIndices(), ExecGetAllUpdatedCols(), ExecGetChildToRootMap(), ExecGetExtraUpdatedCols(), ExecGetInsertedCols(), ExecGetRangeTableRelation(), ExecGetReturningSlot(), ExecGetTriggerNewSlot(), ExecGetTriggerOldSlot(), ExecGetUpdatedCols(), ExecGetUpdateNewTuple(), ExecInitResultRelation(), ExecInsertIndexTuples(), ExecLookupResultRelByOid(), ExecOpenIndices(), ExecSimpleRelationDelete(), ExecSimpleRelationInsert(), ExecSimpleRelationUpdate(), ExecTargetListLength(), executor_errposition(), GetAttributeByName(), GetAttributeByNum(), list_nth(), RegisterExprContextCallback(), RelationFindReplTupleByIndex(), RelationFindReplTupleSeq(), relname, UnregisterExprContextCallback(), and values.

Referenced by conversion_error_callback(), ExecEvalWholeRowVar(), ExecGetExtraUpdatedCols(), ExecGetInsertedCols(), ExecGetRangeTableRelation(), ExecGetUpdatedCols(), ExecInitBitmapIndexScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), InitPlan(), postgresBeginDirectModify(), postgresBeginForeignInsert(), postgresBeginForeignModify(), and postgresBeginForeignScan().

571 {
572  return (RangeTblEntry *) list_nth(estate->es_range_table, rti - 1);
573 }
List * es_range_table
Definition: execnodes.h:558
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

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

537 {
538  planstate->ps_ProjInfo =
540  planstate->ps_ExprContext,
541  planstate->ps_ResultTupleSlot,
542  planstate,
543  inputDesc);
544 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1004
ExprContext * ps_ExprContext
Definition: execnodes.h:1003
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1002
Plan * plan
Definition: execnodes.h:964
List * targetlist
Definition: plannodes.h:141
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:353

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
Index  varno 
)

Definition at line 285 of file execScan.c.

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

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

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

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 670 of file execUtils.c.

References ExecSetSlotDescriptor(), and ScanState::ss_ScanTupleSlot.

Referenced by ExecWorkTableScan().

671 {
672  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
673 
674  ExecSetSlotDescriptor(slot, tupDesc);
675 }
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1376
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:1259

◆ ExecBuildAggTrans()

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

Referenced by ExecProcNode().

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2289 of file execMain.c.

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

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

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

◆ ExecBuildGroupingEqual()

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

Definition at line 3629 of file execExpr.c.

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

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

3636 {
3638  ExprEvalStep scratch = {0};
3639  int maxatt = -1;
3640  List *adjust_jumps = NIL;
3641  ListCell *lc;
3642 
3643  /*
3644  * When no columns are actually compared, the result's always true. See
3645  * special case in ExecQual().
3646  */
3647  if (numCols == 0)
3648  return NULL;
3649 
3650  state->expr = NULL;
3651  state->flags = EEO_FLAG_IS_QUAL;
3652  state->parent = parent;
3653 
3654  scratch.resvalue = &state->resvalue;
3655  scratch.resnull = &state->resnull;
3656 
3657  /* compute max needed attribute */
3658  for (int natt = 0; natt < numCols; natt++)
3659  {
3660  int attno = keyColIdx[natt];
3661 
3662  if (attno > maxatt)
3663  maxatt = attno;
3664  }
3665  Assert(maxatt >= 0);
3666 
3667  /* push deform steps */
3668  scratch.opcode = EEOP_INNER_FETCHSOME;
3669  scratch.d.fetch.last_var = maxatt;
3670  scratch.d.fetch.fixed = false;
3671  scratch.d.fetch.known_desc = ldesc;
3672  scratch.d.fetch.kind = lops;
3673  if (ExecComputeSlotInfo(state, &scratch))
3674  ExprEvalPushStep(state, &scratch);
3675 
3676  scratch.opcode = EEOP_OUTER_FETCHSOME;
3677  scratch.d.fetch.last_var = maxatt;
3678  scratch.d.fetch.fixed = false;
3679  scratch.d.fetch.known_desc = rdesc;
3680  scratch.d.fetch.kind = rops;
3681  if (ExecComputeSlotInfo(state, &scratch))
3682  ExprEvalPushStep(state, &scratch);
3683 
3684  /*
3685  * Start comparing at the last field (least significant sort key). That's
3686  * the most likely to be different if we are dealing with sorted input.
3687  */
3688  for (int natt = numCols; --natt >= 0;)
3689  {
3690  int attno = keyColIdx[natt];
3691  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3692  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3693  Oid foid = eqfunctions[natt];
3694  Oid collid = collations[natt];
3695  FmgrInfo *finfo;
3696  FunctionCallInfo fcinfo;
3697  AclResult aclresult;
3698 
3699  /* Check permission to call function */
3700  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
3701  if (aclresult != ACLCHECK_OK)
3702  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3703 
3705 
3706  /* Set up the primary fmgr lookup information */
3707  finfo = palloc0(sizeof(FmgrInfo));
3708  fcinfo = palloc0(SizeForFunctionCallInfo(2));
3709  fmgr_info(foid, finfo);
3710  fmgr_info_set_expr(NULL, finfo);
3711  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3712  collid, NULL, NULL);
3713 
3714  /* left arg */
3715  scratch.opcode = EEOP_INNER_VAR;
3716  scratch.d.var.attnum = attno - 1;
3717  scratch.d.var.vartype = latt->atttypid;
3718  scratch.resvalue = &fcinfo->args[0].value;
3719  scratch.resnull = &fcinfo->args[0].isnull;
3720  ExprEvalPushStep(state, &scratch);
3721 
3722  /* right arg */
3723  scratch.opcode = EEOP_OUTER_VAR;
3724  scratch.d.var.attnum = attno - 1;
3725  scratch.d.var.vartype = ratt->atttypid;
3726  scratch.resvalue = &fcinfo->args[1].value;
3727  scratch.resnull = &fcinfo->args[1].isnull;
3728  ExprEvalPushStep(state, &scratch);
3729 
3730  /* evaluate distinctness */
3731  scratch.opcode = EEOP_NOT_DISTINCT;
3732  scratch.d.func.finfo = finfo;
3733  scratch.d.func.fcinfo_data = fcinfo;
3734  scratch.d.func.fn_addr = finfo->fn_addr;
3735  scratch.d.func.nargs = 2;
3736  scratch.resvalue = &state->resvalue;
3737  scratch.resnull = &state->resnull;
3738  ExprEvalPushStep(state, &scratch);
3739 
3740  /* then emit EEOP_QUAL to detect if result is false (or null) */
3741  scratch.opcode = EEOP_QUAL;
3742  scratch.d.qualexpr.jumpdone = -1;
3743  scratch.resvalue = &state->resvalue;
3744  scratch.resnull = &state->resnull;
3745  ExprEvalPushStep(state, &scratch);
3746  adjust_jumps = lappend_int(adjust_jumps,
3747  state->steps_len - 1);
3748  }
3749 
3750  /* adjust jump targets */
3751  foreach(lc, adjust_jumps)
3752  {
3753  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3754 
3755  Assert(as->opcode == EEOP_QUAL);
3756  Assert(as->d.qualexpr.jumpdone == -1);
3757  as->d.qualexpr.jumpdone = state->steps_len;
3758  }
3759 
3760  scratch.resvalue = NULL;
3761  scratch.resnull = NULL;
3762  scratch.opcode = EEOP_DONE;
3763  ExprEvalPushStep(state, &scratch);
3764 
3765  ExecReadyExpr(state);
3766 
3767  return state;
3768 }
#define NIL
Definition: pg_list.h:65
Definition: fmgr.h:56
struct PlanState * parent
Definition: execnodes.h:108
Datum * resvalue
Definition: execExpr.h:273
struct ExprEvalStep::@49::@50 fetch
Oid GetUserId(void)
Definition: miscinit.c:478
PGFunction fn_addr
Definition: fmgr.h:58
struct ExprEvalStep * steps
Definition: execnodes.h:85
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
struct ExprEvalStep::@49::@58 qualexpr
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
bool * resnull
Definition: execExpr.h:274
unsigned int Oid
Definition: postgres_ext.h:31
struct ExprEvalStep::@49::@51 var
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
bool resnull
Definition: execnodes.h:72
union ExprEvalStep::@49 d
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:170
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1579
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
Datum value
Definition: postgres.h:422
List * lappend_int(List *list, int datum)
Definition: list.c:354
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
void * palloc0(Size size)
Definition: mcxt.c:1093
AclResult
Definition: acl.h:177
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2622
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2375
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:829
struct ExprEvalStep::@49::@56 func
#define makeNode(_type_)
Definition: nodes.h:587
#define Assert(condition)
Definition: c.h:804
Definition: regguts.h:317
intptr_t opcode
Definition: execExpr.h:270
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
int steps_len
Definition: execnodes.h:104
#define ACL_EXECUTE
Definition: parsenodes.h:89
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4723
uint8 flags
Definition: execnodes.h:65
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:74

◆ ExecBuildParamSetEqual()

ExprState* ExecBuildParamSetEqual ( TupleDesc  desc,
const TupleTableSlotOps lops,
const TupleTableSlotOps rops,
const Oid eqfunctions,
const Oid collations,
const List param_exprs,
PlanState parent 
)

Definition at line 3786 of file execExpr.c.

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

Referenced by ExecInitResultCache(), and ExecProcNode().

3793 {
3795  ExprEvalStep scratch = {0};
3796  int maxatt = list_length(param_exprs);
3797  List *adjust_jumps = NIL;
3798  ListCell *lc;
3799 
3800  state->expr = NULL;
3801  state->flags = EEO_FLAG_IS_QUAL;
3802  state->parent = parent;
3803 
3804  scratch.resvalue = &state->resvalue;
3805  scratch.resnull = &state->resnull;
3806 
3807  /* push deform steps */
3808  scratch.opcode = EEOP_INNER_FETCHSOME;
3809  scratch.d.fetch.last_var = maxatt;
3810  scratch.d.fetch.fixed = false;
3811  scratch.d.fetch.known_desc = desc;
3812  scratch.d.fetch.kind = lops;
3813  if (ExecComputeSlotInfo(state, &scratch))
3814  ExprEvalPushStep(state, &scratch);
3815 
3816  scratch.opcode = EEOP_OUTER_FETCHSOME;
3817  scratch.d.fetch.last_var = maxatt;
3818  scratch.d.fetch.fixed = false;
3819  scratch.d.fetch.known_desc = desc;
3820  scratch.d.fetch.kind = rops;
3821  if (ExecComputeSlotInfo(state, &scratch))
3822  ExprEvalPushStep(state, &scratch);
3823 
3824  for (int attno = 0; attno < maxatt; attno++)
3825  {
3826  Form_pg_attribute att = TupleDescAttr(desc, attno);
3827  Oid foid = eqfunctions[attno];
3828  Oid collid = collations[attno];
3829  FmgrInfo *finfo;
3830  FunctionCallInfo fcinfo;
3831  AclResult aclresult;
3832 
3833  /* Check permission to call function */
3834  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
3835  if (aclresult != ACLCHECK_OK)
3836  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3837 
3839 
3840  /* Set up the primary fmgr lookup information */
3841  finfo = palloc0(sizeof(FmgrInfo));
3842  fcinfo = palloc0(SizeForFunctionCallInfo(2));
3843  fmgr_info(foid, finfo);
3844  fmgr_info_set_expr(NULL, finfo);
3845  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3846  collid, NULL, NULL);
3847 
3848  /* left arg */
3849  scratch.opcode = EEOP_INNER_VAR;
3850  scratch.d.var.attnum = attno;
3851  scratch.d.var.vartype = att->atttypid;
3852  scratch.resvalue = &fcinfo->args[0].value;
3853  scratch.resnull = &fcinfo->args[0].isnull;
3854  ExprEvalPushStep(state, &scratch);
3855 
3856  /* right arg */
3857  scratch.opcode = EEOP_OUTER_VAR;
3858  scratch.d.var.attnum = attno;
3859  scratch.d.var.vartype = att->atttypid;
3860  scratch.resvalue = &fcinfo->args[1].value;
3861  scratch.resnull = &fcinfo->args[1].isnull;
3862  ExprEvalPushStep(state, &scratch);
3863 
3864  /* evaluate distinctness */
3865  scratch.opcode = EEOP_NOT_DISTINCT;
3866  scratch.d.func.finfo = finfo;
3867  scratch.d.func.fcinfo_data = fcinfo;
3868  scratch.d.func.fn_addr = finfo->fn_addr;
3869  scratch.d.func.nargs = 2;
3870  scratch.resvalue = &state->resvalue;
3871  scratch.resnull = &state->resnull;
3872  ExprEvalPushStep(state, &scratch);
3873 
3874  /* then emit EEOP_QUAL to detect if result is false (or null) */
3875  scratch.opcode = EEOP_QUAL;
3876  scratch.d.qualexpr.jumpdone = -1;
3877  scratch.resvalue = &state->resvalue;
3878  scratch.resnull = &state->resnull;
3879  ExprEvalPushStep(state, &scratch);
3880  adjust_jumps = lappend_int(adjust_jumps,
3881  state->steps_len - 1);
3882  }
3883 
3884  /* adjust jump targets */
3885  foreach(lc, adjust_jumps)
3886  {
3887  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3888 
3889  Assert(as->opcode == EEOP_QUAL);
3890  Assert(as->d.qualexpr.jumpdone == -1);
3891  as->d.qualexpr.jumpdone = state->steps_len;
3892  }
3893 
3894  scratch.resvalue = NULL;
3895  scratch.resnull = NULL;
3896  scratch.opcode = EEOP_DONE;
3897  ExprEvalPushStep(state, &scratch);
3898 
3899  ExecReadyExpr(state);
3900 
3901  return state;
3902 }
#define NIL
Definition: pg_list.h:65
Definition: fmgr.h:56
struct PlanState * parent
Definition: execnodes.h:108
Datum * resvalue
Definition: execExpr.h:273
struct ExprEvalStep::@49::@50 fetch
Oid GetUserId(void)
Definition: miscinit.c:478
PGFunction fn_addr
Definition: fmgr.h:58
struct ExprEvalStep * steps
Definition: execnodes.h:85
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
struct ExprEvalStep::@49::@58 qualexpr
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
bool * resnull
Definition: execExpr.h:274
unsigned int Oid
Definition: postgres_ext.h:31
struct ExprEvalStep::@49::@51 var
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
bool resnull
Definition: execnodes.h:72
union ExprEvalStep::@49 d
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:170
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1579
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
Datum value
Definition: postgres.h:422
List * lappend_int(List *list, int datum)
Definition: list.c:354
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
void * palloc0(Size size)
Definition: mcxt.c:1093
AclResult
Definition: acl.h:177
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2622
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2375
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:829
struct ExprEvalStep::@49::@56 func
#define makeNode(_type_)
Definition: nodes.h:587
#define Assert(condition)
Definition: c.h:804
Definition: regguts.h:317
intptr_t opcode
Definition: execExpr.h:270
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
static int list_length(const List *l)
Definition: pg_list.h:149
int steps_len
Definition: execnodes.h:104
#define ACL_EXECUTE
Definition: parsenodes.h:89
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4723
uint8 flags
Definition: execnodes.h:65
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:74

◆ ExecBuildProjectionInfo()

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

Definition at line 353 of file execExpr.c.

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

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

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

◆ ExecBuildUpdateProjection()

ProjectionInfo* ExecBuildUpdateProjection ( List subTargetList,
List targetColnos,
TupleDesc  relDesc,
ExprContext econtext,
TupleTableSlot slot,
PlanState parent 
)

Definition at line 506 of file execExpr.c.

References Assert, ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, attnum, bms_add_member(), bms_is_member(), ExprEvalStep::constval, ExprEvalStep::d, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_CONST, EEOP_DONE, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecPushExprSlots(), ExecReadyExpr(), ExprState::expr, TargetEntry::expr, ExprEvalPushStep(), exprType(), ExprState::ext_params, forboth, format_type_be(), LastAttnumInfo::last_outer, LastAttnumInfo::last_scan, lfirst_int, lfirst_node, list_length(), makeNode, TupleDescData::natts, ExprEvalStep::opcode, ExprState::parent, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TargetEntry::resjunk, ExprState::resnull, ExprEvalStep::resnull, ExprState::resultslot, ExprState::resvalue, ExprEvalStep::resvalue, T_ExprState, ExprState::tag, and TupleDescAttr.

Referenced by ExecInitUpdateProjection(), and ExecProcNode().

512 {
514  ExprState *state;
515  int nAssignableCols;
516  bool sawJunk;
517  Bitmapset *assignedCols;
518  LastAttnumInfo deform = {0, 0, 0};
519  ExprEvalStep scratch = {0};
520  int outerattnum;
521  ListCell *lc,
522  *lc2;
523 
524  projInfo->pi_exprContext = econtext;
525  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
526  projInfo->pi_state.tag = T_ExprState;
527  state = &projInfo->pi_state;
528  state->expr = NULL; /* not used */
529  state->parent = parent;
530  state->ext_params = NULL;
531 
532  state->resultslot = slot;
533 
534  /*
535  * Examine the subplan tlist to see how many non-junk columns there are,
536  * and to verify that the non-junk columns come before the junk ones.
537  */
538  nAssignableCols = 0;
539  sawJunk = false;
540  foreach(lc, subTargetList)
541  {
542  TargetEntry *tle = lfirst_node(TargetEntry, lc);
543 
544  if (tle->resjunk)
545  sawJunk = true;
546  else
547  {
548  if (sawJunk)
549  elog(ERROR, "subplan target list is out of order");
550  nAssignableCols++;
551  }
552  }
553 
554  /* We should have one targetColnos entry per non-junk column */
555  if (nAssignableCols != list_length(targetColnos))
556  elog(ERROR, "targetColnos does not match subplan target list");
557 
558  /*
559  * Build a bitmapset of the columns in targetColnos. (We could just use
560  * list_member_int() tests, but that risks O(N^2) behavior with many
561  * columns.)
562  */
563  assignedCols = NULL;
564  foreach(lc, targetColnos)
565  {
566  AttrNumber targetattnum = lfirst_int(lc);
567 
568  assignedCols = bms_add_member(assignedCols, targetattnum);
569  }
570 
571  /*
572  * We want to insert EEOP_*_FETCHSOME steps to ensure the outer and scan
573  * tuples are sufficiently deconstructed. Outer tuple is easy, but for
574  * scan tuple we must find out the last old column we need.
575  */
576  deform.last_outer = nAssignableCols;
577 
578  for (int attnum = relDesc->natts; attnum > 0; attnum--)
579  {
580  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
581 
582  if (attr->attisdropped)
583  continue;
584  if (bms_is_member(attnum, assignedCols))
585  continue;
586  deform.last_scan = attnum;
587  break;
588  }
589 
590  ExecPushExprSlots(state, &deform);
591 
592  /*
593  * Now generate code to fetch data from the outer tuple, incidentally
594  * validating that it'll be of the right type. The checks above ensure
595  * that the forboth() will iterate over exactly the non-junk columns.
596  */
597  outerattnum = 0;
598  forboth(lc, subTargetList, lc2, targetColnos)
599  {
600  TargetEntry *tle = lfirst_node(TargetEntry, lc);
601  AttrNumber targetattnum = lfirst_int(lc2);
602  Form_pg_attribute attr;
603 
604  Assert(!tle->resjunk);
605 
606  /*
607  * Apply sanity checks comparable to ExecCheckPlanOutput().
608  */
609  if (targetattnum <= 0 || targetattnum > relDesc->natts)
610  ereport(ERROR,
611  (errcode(ERRCODE_DATATYPE_MISMATCH),
612  errmsg("table row type and query-specified row type do not match"),
613  errdetail("Query has too many columns.")));
614  attr = TupleDescAttr(relDesc, targetattnum - 1);
615 
616  if (attr->attisdropped)
617  ereport(ERROR,
618  (errcode(ERRCODE_DATATYPE_MISMATCH),
619  errmsg("table row type and query-specified row type do not match"),
620  errdetail("Query provides a value for a dropped column at ordinal position %d.",
621  targetattnum)));
622  if (exprType((Node *) tle->expr) != attr->atttypid)
623  ereport(ERROR,
624  (errcode(ERRCODE_DATATYPE_MISMATCH),
625  errmsg("table row type and query-specified row type do not match"),
626  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
627  format_type_be(attr->atttypid),
628  targetattnum,
629  format_type_be(exprType((Node *) tle->expr)))));
630 
631  /*
632  * OK, build an outer-tuple reference.
633  */
634  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
635  scratch.d.assign_var.attnum = outerattnum++;
636  scratch.d.assign_var.resultnum = targetattnum - 1;
637  ExprEvalPushStep(state, &scratch);
638  }
639 
640  /*
641  * Now generate code to copy over any old columns that were not assigned
642  * to, and to ensure that dropped columns are set to NULL.
643  */
644  for (int attnum = 1; attnum <= relDesc->natts; attnum++)
645  {
646  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
647 
648  if (attr->attisdropped)
649  {
650  /* Put a null into the ExprState's resvalue/resnull ... */
651  scratch.opcode = EEOP_CONST;
652  scratch.resvalue = &state->resvalue;
653  scratch.resnull = &state->resnull;
654  scratch.d.constval.value = (Datum) 0;
655  scratch.d.constval.isnull = true;
656  ExprEvalPushStep(state, &scratch);
657  /* ... then assign it to the result slot */
658  scratch.opcode = EEOP_ASSIGN_TMP;
659  scratch.d.assign_tmp.resultnum = attnum - 1;
660  ExprEvalPushStep(state, &scratch);
661  }
662  else if (!bms_is_member(attnum, assignedCols))
663  {
664  /* Certainly the right type, so needn't check */
665  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
666  scratch.d.assign_var.attnum = attnum - 1;
667  scratch.d.assign_var.resultnum = attnum - 1;
668  ExprEvalPushStep(state, &scratch);
669  }
670  }
671 
672  scratch.opcode = EEOP_DONE;
673  ExprEvalPushStep(state, &scratch);
674 
675  ExecReadyExpr(state);
676 
677  return projInfo;
678 }
NodeTag tag
Definition: execnodes.h:63
struct PlanState * parent
Definition: execnodes.h:108
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
Datum * resvalue
Definition: execExpr.h:273
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
bool * resnull
Definition: execExpr.h:274
ParamListInfo ext_params
Definition: execnodes.h:109
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
TupleTableSlot * resultslot
Definition: execnodes.h:80
bool resjunk
Definition: primnodes.h:1451
#define ERROR
Definition: elog.h:46
bool resnull
Definition: execnodes.h:72
union ExprEvalStep::@49 d
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:170
#define lfirst_node(type, lc)
Definition: pg_list.h:172
struct ExprEvalStep::@49::@55 constval
AttrNumber last_scan
Definition: execExpr.c:58
int errdetail(const char *fmt,...)
Definition: elog.c:1042
AttrNumber last_outer
Definition: execExpr.c:57
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
Definition: execExpr.c:2524
struct ExprEvalStep::@49::@53 assign_var
uintptr_t Datum
Definition: postgres.h:411
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2375
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:829
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:157
#define makeNode(_type_)
Definition: nodes.h:587
#define Assert(condition)
Definition: c.h:804
Definition: regguts.h:317
intptr_t opcode
Definition: execExpr.h:270
Expr * expr
Definition: primnodes.h:1444
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:149
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
ExprState pi_state
Definition: execnodes.h:333
struct ExprEvalStep::@49::@54 assign_tmp
ExprContext * pi_exprContext
Definition: execnodes.h:335
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
Datum resvalue
Definition: execnodes.h:74
int16 AttrNumber
Definition: attnum.h:21

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext context 
)

Definition at line 799 of file execExpr.c.

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

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

800 {
801  Datum ret;
802  bool isnull;
803 
804  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
805  if (state == NULL)
806  return true;
807 
808  /* verify that expression was not compiled using ExecInitQual */
809  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
810 
811  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
812 
813  if (isnull)
814  return true;
815 
816  return DatumGetBool(ret);
817 }
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:330
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
#define DatumGetBool(X)
Definition: postgres.h:437
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
uint8 flags
Definition: execnodes.h:65

◆ ExecCheckIndexConstraints()

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

Definition at line 505 of file execIndexing.c.

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

Referenced by exec_rt_fetch(), and ExecInsert().

508 {
509  int i;
510  int numIndices;
511  RelationPtr relationDescs;
512  Relation heapRelation;
513  IndexInfo **indexInfoArray;
514  ExprContext *econtext;
516  bool isnull[INDEX_MAX_KEYS];
517  ItemPointerData invalidItemPtr;
518  bool checkedIndex = false;
519 
520  ItemPointerSetInvalid(conflictTid);
521  ItemPointerSetInvalid(&invalidItemPtr);
522 
523  /*
524  * Get information from the result relation info structure.
525  */
526  numIndices = resultRelInfo->ri_NumIndices;
527  relationDescs = resultRelInfo->ri_IndexRelationDescs;
528  indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
529  heapRelation = resultRelInfo->ri_RelationDesc;
530 
531  /*
532  * We will use the EState's per-tuple context for evaluating predicates
533  * and index expressions (creating it if it's not already there).
534  */
535  econtext = GetPerTupleExprContext(estate);
536 
537  /* Arrange for econtext's scan tuple to be the tuple under test */
538  econtext->ecxt_scantuple = slot;
539 
540  /*
541  * For each index, form index tuple and check if it satisfies the
542  * constraint.
543  */
544  for (i = 0; i < numIndices; i++)
545  {
546  Relation indexRelation = relationDescs[i];
547  IndexInfo *indexInfo;
548  bool satisfiesConstraint;
549 
550  if (indexRelation == NULL)
551  continue;
552 
553  indexInfo = indexInfoArray[i];
554 
555  if (!indexInfo->ii_Unique && !indexInfo->ii_ExclusionOps)
556  continue;
557 
558  /* If the index is marked as read-only, ignore it */
559  if (!indexInfo->ii_ReadyForInserts)
560  continue;
561 
562  /* When specific arbiter indexes requested, only examine them */
563  if (arbiterIndexes != NIL &&
564  !list_member_oid(arbiterIndexes,
565  indexRelation->rd_index->indexrelid))
566  continue;
567 
568  if (!indexRelation->rd_index->indimmediate)
569  ereport(ERROR,
570  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
571  errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),
572  errtableconstraint(heapRelation,
573  RelationGetRelationName(indexRelation))));
574 
575  checkedIndex = true;
576 
577  /* Check for partial index */
578  if (indexInfo->ii_Predicate != NIL)
579  {
580  ExprState *predicate;
581 
582  /*
583  * If predicate state not set up yet, create it (in the estate's
584  * per-query context)
585  */
586  predicate = indexInfo->ii_PredicateState;
587  if (predicate == NULL)
588  {
589  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
590  indexInfo->ii_PredicateState = predicate;
591  }
592 
593  /* Skip this index-update if the predicate isn't satisfied */
594  if (!ExecQual(predicate, econtext))
595  continue;
596  }
597 
598  /*
599  * FormIndexDatum fills in its values and isnull parameters with the
600  * appropriate values for the column(s) of the index.
601  */
602  FormIndexDatum(indexInfo,
603  slot,
604  estate,
605  values,
606  isnull);
607 
608  satisfiesConstraint =
609  check_exclusion_or_unique_constraint(heapRelation, indexRelation,
610  indexInfo, &invalidItemPtr,
611  values, isnull, estate, false,
612  CEOUC_WAIT, true,
613  conflictTid);
614  if (!satisfiesConstraint)
615  return false;
616  }
617 
618  if (arbiterIndexes != NIL && !checkedIndex)
619  elog(ERROR, "unexpected failure to find arbiter index");
620 
621  return true;
622 }
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:2827
int ri_NumIndices
Definition: execnodes.h:414
#define NIL
Definition: pg_list.h:65
Relation ri_RelationDesc
Definition: execnodes.h:411
List * ii_Predicate
Definition: execnodes.h:163
ExprState * ii_PredicateState
Definition: execnodes.h:164
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:395
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:667
#define GetPerTupleExprContext(estate)
Definition: executor.h:532
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5588
Form_pg_index rd_index
Definition: rel.h:175
#define ERROR
Definition: elog.h:46
#define RelationGetRelationName(relation)
Definition: rel.h:491
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:720
bool ii_ReadyForInserts
Definition: execnodes.h:173
uintptr_t Datum
Definition: postgres.h:411
#define ereport(elevel,...)
Definition: elog.h:157
bool ii_Unique
Definition: execnodes.h:172
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:689
#define INDEX_MAX_KEYS
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
Oid * ii_ExclusionOps
Definition: execnodes.h:165
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:420
int i
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:417

◆ ExecCheckRTPerms()

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

Definition at line 568 of file execMain.c.

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

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

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1147 of file execUtils.c.

References lfirst_node, and TargetEntry::resjunk.

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

1148 {
1149  int len = 0;
1150  ListCell *tl;
1151 
1152  foreach(tl, targetlist)
1153  {
1154  TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1155 
1156  if (!curTle->resjunk)
1157  len++;
1158  }
1159  return len;
1160 }
bool resjunk
Definition: primnodes.h:1451
#define lfirst_node(type, lc)
Definition: pg_list.h:172

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 1920 of file execTuples.c.

References ExecTypeFromTLInternal().

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

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 231 of file execIndexing.c.

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

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

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

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1482 of file execMain.c.

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

Referenced by CopyFrom(), and ExecEndPlan().

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

◆ ExecCloseResultRelations()

void ExecCloseResultRelations ( EState estate)

Definition at line 1439 of file execMain.c.

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

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

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

◆ ExecConditionalAssignProjectionInfo()

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

Definition at line 555 of file execUtils.c.

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

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

557 {
558  if (tlist_matches_tupdesc(planstate,
559  planstate->plan->targetlist,
560  varno,
561  inputDesc))
562  {
563  planstate->ps_ProjInfo = NULL;
564  planstate->resultopsset = planstate->scanopsset;
565  planstate->resultopsfixed = planstate->scanopsfixed;
566  planstate->resultops = planstate->scanops;
567  }
568  else
569  {
570  if (!planstate->ps_ResultTupleSlot)
571  {
572  ExecInitResultSlot(planstate, &TTSOpsVirtual);
573  planstate->resultops = &TTSOpsVirtual;
574  planstate->resultopsfixed = true;
575  planstate->resultopsset = true;
576  }
577  ExecAssignProjectionInfo(planstate, inputDesc);
578  }
579 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1004
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
const TupleTableSlotOps * resultops
Definition: execnodes.h:1039
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1002
const TupleTableSlotOps * scanops
Definition: execnodes.h:1036
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:535
bool resultopsset
Definition: execnodes.h:1047
Plan * plan
Definition: execnodes.h:964
bool scanopsfixed
Definition: execnodes.h:1040
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1749
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
Definition: execUtils.c:582
bool scanopsset
Definition: execnodes.h:1044
List * targetlist
Definition: plannodes.h:141
bool resultopsfixed
Definition: execnodes.h:1043

◆ ExecConstraints()

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

Definition at line 1821 of file execMain.c.

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

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

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

◆ ExecCreateScanSlotFromOuterPlan()

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

Definition at line 682 of file execUtils.c.

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

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

685 {
687  TupleDesc tupDesc;
688 
689  outerPlan = outerPlanState(scanstate);
690  tupDesc = ExecGetResultType(outerPlan);
691 
692  ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
693 }
#define outerPlanState(node)
Definition: execnodes.h:1058
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1781
#define outerPlan(node)
Definition: plannodes.h:171
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:490

◆ execCurrentOf()

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

Definition at line 44 of file execCurrent.c.

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

Referenced by TidListEval().

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

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 555 of file execProcnode.c.

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

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

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

◆ ExecEvalExpr()