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_EXPLAIN_GENERIC   0x0002 /* EXPLAIN (GENERIC_PLAN) */
 
#define EXEC_FLAG_REWIND   0x0004 /* need efficient rescan */
 
#define EXEC_FLAG_BACKWARD   0x0008 /* need backward scan */
 
#define EXEC_FLAG_MARK   0x0010 /* need mark/restore */
 
#define EXEC_FLAG_SKIP_TRIGGERS   0x0020 /* skip AfterTrigger setup */
 
#define EXEC_FLAG_WITH_NO_DATA   0x0040 /* REFRESH ... WITH NO DATA */
 
#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 *rangeTable, List *rtePermInfos, bool ereport_on_violation)
 
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 ExecCheckPermissions (List *rangeTable, List *rteperminfos, bool ereport_on_violation)
 
void CheckValidResultRel (ResultRelInfo *resultRelInfo, CmdType operation, List *mergeActions)
 
void InitResultRelInfo (ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
 
ResultRelInfoExecGetTriggerResultRel (EState *estate, Oid relid, ResultRelInfo *rootRelInfo)
 
ListExecGetAncestorResultRels (EState *estate, ResultRelInfo *resultRelInfo)
 
void 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 *inputslot)
 
void EvalPlanQualInit (EPQState *epqstate, EState *parentestate, Plan *subplan, List *auxrowmarks, int epqParam, List *resultRelations)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
TupleTableSlotEvalPlanQualSlot (EPQState *epqstate, Relation relation, Index rti)
 
bool EvalPlanQualFetchRowMark (EPQState *epqstate, Index rti, TupleTableSlot *slot)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate)
 
void EvalPlanQualEnd (EPQState *epqstate)
 
PlanStateExecInitNode (Plan *node, EState *estate, int eflags)
 
void ExecSetExecProcNode (PlanState *node, ExecProcNodeMtd function)
 
NodeMultiExecProcNode (PlanState *node)
 
void ExecEndNode (PlanState *node)
 
void 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 *targetList, bool evalTargetList, 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 *econtext)
 
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, int 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, const Datum *values, const 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, int varno)
 
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, List *permInfos)
 
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)
 
TupleConversionMapExecGetRootToChildMap (ResultRelInfo *resultRelInfo, EState *estate)
 
Oid ExecGetResultRelCheckAsUser (ResultRelInfo *relInfo, EState *estate)
 
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 onlySummarizing)
 
bool ExecCheckIndexConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, List *arbiterIndexes)
 
void check_exclusion_constraint (Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex)
 
StrategyNumber get_equal_strategy_number_for_am (Oid am)
 
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)
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
text * cstring_to_text(const char *s)
Definition: varlena.c:184

Definition at line 522 of file executor.h.

◆ EvalPlanQualSetSlot

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

Definition at line 244 of file executor.h.

◆ EXEC_FLAG_BACKWARD

#define EXEC_FLAG_BACKWARD   0x0008 /* need backward scan */

Definition at line 68 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_GENERIC

#define EXEC_FLAG_EXPLAIN_GENERIC   0x0002 /* EXPLAIN (GENERIC_PLAN) */

Definition at line 66 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_ONLY

#define EXEC_FLAG_EXPLAIN_ONLY   0x0001 /* EXPLAIN, no ANALYZE */

Definition at line 65 of file executor.h.

◆ EXEC_FLAG_MARK

#define EXEC_FLAG_MARK   0x0010 /* need mark/restore */

Definition at line 69 of file executor.h.

◆ EXEC_FLAG_REWIND

#define EXEC_FLAG_REWIND   0x0004 /* need efficient rescan */

Definition at line 67 of file executor.h.

◆ EXEC_FLAG_SKIP_TRIGGERS

#define EXEC_FLAG_SKIP_TRIGGERS   0x0020 /* skip AfterTrigger setup */

Definition at line 70 of file executor.h.

◆ EXEC_FLAG_WITH_NO_DATA

#define EXEC_FLAG_WITH_NO_DATA   0x0040 /* REFRESH ... WITH NO DATA */

Definition at line 71 of file executor.h.

◆ GetPerTupleExprContext

#define GetPerTupleExprContext (   estate)
Value:
((estate)->es_per_tuple_exprcontext ? \
(estate)->es_per_tuple_exprcontext : \
MakePerTupleExprContext(estate))

Definition at line 550 of file executor.h.

◆ GetPerTupleMemoryContext

#define GetPerTupleMemoryContext (   estate)     (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)

Definition at line 555 of file executor.h.

◆ ResetExprContext

#define ResetExprContext (   econtext)     MemoryContextReset((econtext)->ecxt_per_tuple_memory)

Definition at line 544 of file executor.h.

◆ ResetPerTupleExprContext

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

Definition at line 559 of file executor.h.

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 473 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 474 of file executor.h.

◆ ExecutorCheckPerms_hook_type

typedef bool(* ExecutorCheckPerms_hook_type) (List *rangeTable, List *rtePermInfos, bool ereport_on_violation)

Definition at line 94 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 90 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 86 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 79 of file executor.h.

◆ ExecutorStart_hook_type

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

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

2257 {
2258  TupOutputState *tstate;
2259 
2260  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2261 
2262  tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2263  tstate->dest = dest;
2264 
2265  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2266 
2267  return tstate;
2268 }
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1237
void * palloc(Size size)
Definition: mcxt.c:1304
@ CMD_SELECT
Definition: nodes.h:255
TupleTableSlot * slot
Definition: executor.h:506
DestReceiver * dest
Definition: executor.h:507
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:120

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

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

◆ 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 254 of file execGrouping.c.

264 {
265  return BuildTupleHashTableExt(parent,
266  inputDesc,
267  numCols, keyColIdx,
268  eqfuncoids,
269  hashfunctions,
270  collations,
271  nbuckets, additionalsize,
272  tablecxt,
273  tablecxt,
274  tempcxt,
275  use_variable_hash_iv);
276 }
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:153

References BuildTupleHashTableExt().

◆ 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 153 of file execGrouping.c.

164 {
165  TupleHashTable hashtable;
166  Size entrysize = sizeof(TupleHashEntryData) + additionalsize;
167  Size hash_mem_limit;
168  MemoryContext oldcontext;
169  bool allow_jit;
170 
171  Assert(nbuckets > 0);
172 
173  /* Limit initial table size request to not more than hash_mem */
174  hash_mem_limit = get_hash_memory_limit() / entrysize;
175  if (nbuckets > hash_mem_limit)
176  nbuckets = hash_mem_limit;
177 
178  oldcontext = MemoryContextSwitchTo(metacxt);
179 
180  hashtable = (TupleHashTable) palloc(sizeof(TupleHashTableData));
181 
182  hashtable->numCols = numCols;
183  hashtable->keyColIdx = keyColIdx;
184  hashtable->tab_hash_funcs = hashfunctions;
185  hashtable->tab_collations = collations;
186  hashtable->tablecxt = tablecxt;
187  hashtable->tempcxt = tempcxt;
188  hashtable->entrysize = entrysize;
189  hashtable->tableslot = NULL; /* will be made on first lookup */
190  hashtable->inputslot = NULL;
191  hashtable->in_hash_funcs = NULL;
192  hashtable->cur_eq_func = NULL;
193 
194  /*
195  * If parallelism is in use, even if the leader backend is performing the
196  * scan itself, we don't want to create the hashtable exactly the same way
197  * in all workers. As hashtables are iterated over in keyspace-order,
198  * doing so in all processes in the same way is likely to lead to
199  * "unbalanced" hashtables when the table size initially is
200  * underestimated.
201  */
202  if (use_variable_hash_iv)
204  else
205  hashtable->hash_iv = 0;
206 
207  hashtable->hashtab = tuplehash_create(metacxt, nbuckets, hashtable);
208 
209  /*
210  * We copy the input tuple descriptor just for safety --- we assume all
211  * input tuples will have equivalent descriptors.
212  */
215 
216  /*
217  * If the old reset interface is used (i.e. BuildTupleHashTable, rather
218  * than BuildTupleHashTableExt), allowing JIT would lead to the generated
219  * functions to a) live longer than the query b) be re-generated each time
220  * the table is being reset. Therefore prevent JIT from being used in that
221  * case, by not providing a parent node (which prevents accessing the
222  * JitContext in the EState).
223  */
224  allow_jit = metacxt != tablecxt;
225 
226  /* build comparator for all columns */
227  /* XXX: should we support non-minimal tuples for the inputslot? */
228  hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
230  numCols,
231  keyColIdx, eqfuncoids, collations,
232  allow_jit ? parent : NULL);
233 
234  /*
235  * While not pretty, it's ok to not shut down this context, but instead
236  * rely on the containing memory context being reset, as
237  * ExecBuildGroupingEqual() only builds a very simple expression calling
238  * functions (i.e. nothing that'd employ RegisterExprContextCallback()).
239  */
241 
242  MemoryContextSwitchTo(oldcontext);
243 
244  return hashtable;
245 }
int ParallelWorkerNumber
Definition: parallel.c:112
size_t Size
Definition: c.h:592
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:3922
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:355
struct TupleHashTableData * TupleHashTable
Definition: execnodes.h:795
struct TupleHashEntryData TupleHashEntryData
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92
Assert(fmt[strlen(fmt) - 1] !='\n')
size_t get_hash_memory_limit(void)
Definition: nodeHash.c:3595
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
AttrNumber * keyColIdx
Definition: execnodes.h:817
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:818
tuplehash_hash * hashtab
Definition: execnodes.h:815
MemoryContext tempcxt
Definition: execnodes.h:822
ExprState * tab_eq_func
Definition: execnodes.h:819
TupleTableSlot * tableslot
Definition: execnodes.h:824
ExprContext * exprcontext
Definition: execnodes.h:830
MemoryContext tablecxt
Definition: execnodes.h:821
TupleTableSlot * inputslot
Definition: execnodes.h:826
ExprState * cur_eq_func
Definition: execnodes.h:828
FmgrInfo * in_hash_funcs
Definition: execnodes.h:827
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133

References Assert(), CreateStandaloneExprContext(), CreateTupleDescCopy(), TupleHashTableData::cur_eq_func, TupleHashTableData::entrysize, ExecBuildGroupingEqual(), TupleHashTableData::exprcontext, get_hash_memory_limit(), TupleHashTableData::hash_iv, TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), 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().

◆ check_exclusion_constraint()

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

Definition at line 915 of file execIndexing.c.

920 {
921  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
922  values, isnull,
923  estate, newIndex,
924  CEOUC_WAIT, false, NULL);
925 }
static Datum values[MAXATTR]
Definition: bootstrap.c:152
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool violationOK, ItemPointer conflictTid)
Definition: execIndexing.c:689
@ CEOUC_WAIT
Definition: execIndexing.c:122
Definition: type.h:95

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), and values.

Referenced by IndexCheckExclusion().

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 652 of file execReplication.c.

653 {
654  PublicationDesc pubdesc;
655 
656  /*
657  * Skip checking the replica identity for partitioned tables, because the
658  * operations are actually performed on the leaf partitions.
659  */
660  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
661  return;
662 
663  /* We only need to do checks for UPDATE and DELETE. */
664  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
665  return;
666 
667  /*
668  * It is only safe to execute UPDATE/DELETE when all columns, referenced
669  * in the row filters from publications which the relation is in, are
670  * valid - i.e. when all referenced columns are part of REPLICA IDENTITY
671  * or the table does not publish UPDATEs or DELETEs.
672  *
673  * XXX We could optimize it by first checking whether any of the
674  * publications have a row filter for this relation. If not and relation
675  * has replica identity then we can avoid building the descriptor but as
676  * this happens only one time it doesn't seem worth the additional
677  * complexity.
678  */
679  RelationBuildPublicationDesc(rel, &pubdesc);
680  if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
681  ereport(ERROR,
682  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
683  errmsg("cannot update table \"%s\"",
685  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
686  else if (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
687  ereport(ERROR,
688  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
689  errmsg("cannot update table \"%s\"",
691  errdetail("Column list used by the publication does not cover the replica identity.")));
692  else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
693  ereport(ERROR,
694  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
695  errmsg("cannot delete from table \"%s\"",
697  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
698  else if (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
699  ereport(ERROR,
700  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
701  errmsg("cannot delete from table \"%s\"",
703  errdetail("Column list used by the publication does not cover the replica identity.")));
704 
705  /* If relation has replica identity we are always good. */
707  return;
708 
709  /* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */
710  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
711  return;
712 
713  /*
714  * This is UPDATE/DELETE and there is no replica identity.
715  *
716  * Check if the table publishes UPDATES or DELETES.
717  */
718  if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
719  ereport(ERROR,
720  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
721  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
723  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
724  else if (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
725  ereport(ERROR,
726  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
727  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
729  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
730 }
#define OidIsValid(objectId)
Definition: c.h:762
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
@ CMD_DELETE
Definition: nodes.h:258
@ CMD_UPDATE
Definition: nodes.h:256
#define RelationGetRelationName(relation)
Definition: rel.h:539
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Definition: relcache.c:5705
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4989
PublicationActions pubactions
bool cols_valid_for_delete
bool cols_valid_for_update
Form_pg_class rd_rel
Definition: rel.h:111

References CMD_DELETE, CMD_UPDATE, PublicationDesc::cols_valid_for_delete, PublicationDesc::cols_valid_for_update, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, OidIsValid, PublicationDesc::pubactions, PublicationActions::pubdelete, PublicationActions::pubupdate, RelationData::rd_rel, RelationBuildPublicationDesc(), RelationGetRelationName, RelationGetReplicaIndex(), PublicationDesc::rf_valid_for_delete, and PublicationDesc::rf_valid_for_update.

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

◆ CheckSubscriptionRelkind()

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

Definition at line 739 of file execReplication.c.

741 {
742  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
743  ereport(ERROR,
744  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
745  errmsg("cannot use relation \"%s.%s\" as logical replication target",
746  nspname, relname),
748 }
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
NameData relname
Definition: pg_class.h:38

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

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

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation,
List mergeActions 
)

Definition at line 1026 of file execMain.c.

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

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

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

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 88 of file execUtils.c.

89 {
90  EState *estate;
91  MemoryContext qcontext;
92  MemoryContext oldcontext;
93 
94  /*
95  * Create the per-query context for this Executor run.
96  */
98  "ExecutorState",
100 
101  /*
102  * Make the EState node within the per-query context. This way, we don't
103  * need a separate pfree() operation for it at shutdown.
104  */
105  oldcontext = MemoryContextSwitchTo(qcontext);
106 
107  estate = makeNode(EState);
108 
109  /*
110  * Initialize all fields of the Executor State structure
111  */
113  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
114  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
115  estate->es_range_table = NIL;
116  estate->es_range_table_size = 0;
117  estate->es_relations = NULL;
118  estate->es_rowmarks = NULL;
119  estate->es_rteperminfos = NIL;
120  estate->es_plannedstmt = NULL;
121 
122  estate->es_junkFilter = NULL;
123 
124  estate->es_output_cid = (CommandId) 0;
125 
126  estate->es_result_relations = NULL;
129  estate->es_trig_target_relations = NIL;
130 
133 
134  estate->es_param_list_info = NULL;
135  estate->es_param_exec_vals = NULL;
136 
137  estate->es_queryEnv = NULL;
138 
139  estate->es_query_cxt = qcontext;
140 
141  estate->es_tupleTable = NIL;
142 
143  estate->es_processed = 0;
144  estate->es_total_processed = 0;
145 
146  estate->es_top_eflags = 0;
147  estate->es_instrument = 0;
148  estate->es_finished = false;
149 
150  estate->es_exprcontexts = NIL;
151 
152  estate->es_subplanstates = NIL;
153 
154  estate->es_auxmodifytables = NIL;
155 
156  estate->es_per_tuple_exprcontext = NULL;
157 
158  estate->es_sourceText = NULL;
159 
160  estate->es_use_parallel_mode = false;
161 
162  estate->es_jit_flags = 0;
163  estate->es_jit = NULL;
164 
165  /*
166  * Return the executor state structure
167  */
168  MemoryContextSwitchTo(oldcontext);
169 
170  return estate;
171 }
uint32 CommandId
Definition: c.h:653
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define makeNode(_type_)
Definition: nodes.h:155
#define NIL
Definition: pg_list.h:68
@ ForwardScanDirection
Definition: sdir.h:28
#define InvalidSnapshot
Definition: snapshot.h:123
uint64 es_processed
Definition: execnodes.h:669
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:628
List * es_tuple_routing_result_relations
Definition: execnodes.h:653
int es_top_eflags
Definition: execnodes.h:674
struct JitContext * es_jit
Definition: execnodes.h:714
int es_instrument
Definition: execnodes.h:675
PlannedStmt * es_plannedstmt
Definition: execnodes.h:631
QueryEnvironment * es_queryEnv
Definition: execnodes.h:662
ResultRelInfo ** es_result_relations
Definition: execnodes.h:640
ParamExecData * es_param_exec_vals
Definition: execnodes.h:660
uint64 es_total_processed
Definition: execnodes.h:671
List * es_range_table
Definition: execnodes.h:624
List * es_rteperminfos
Definition: execnodes.h:630
List * es_exprcontexts
Definition: execnodes.h:678
ParamListInfo es_param_list_info
Definition: execnodes.h:659
bool es_finished
Definition: execnodes.h:676
List * es_insert_pending_result_relations
Definition: execnodes.h:721
MemoryContext es_query_cxt
Definition: execnodes.h:665
List * es_tupleTable
Definition: execnodes.h:667
ScanDirection es_direction
Definition: execnodes.h:621
List * es_trig_target_relations
Definition: execnodes.h:656
int es_jit_flags
Definition: execnodes.h:713
List * es_opened_result_relations
Definition: execnodes.h:643
bool es_use_parallel_mode
Definition: execnodes.h:699
Relation * es_relations
Definition: execnodes.h:626
List * es_subplanstates
Definition: execnodes.h:680
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:689
CommandId es_output_cid
Definition: execnodes.h:637
Index es_range_table_size
Definition: execnodes.h:625
List * es_insert_pending_modifytables
Definition: execnodes.h:722
const char * es_sourceText
Definition: execnodes.h:632
Snapshot es_snapshot
Definition: execnodes.h:622
List * es_auxmodifytables
Definition: execnodes.h:682
JunkFilter * es_junkFilter
Definition: execnodes.h:634
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:623

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, EState::es_auxmodifytables, EState::es_crosscheck_snapshot, EState::es_direction, EState::es_exprcontexts, EState::es_finished, EState::es_insert_pending_modifytables, EState::es_insert_pending_result_relations, 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_rteperminfos, EState::es_snapshot, EState::es_sourceText, EState::es_subplanstates, EState::es_top_eflags, EState::es_total_processed, 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_edata_for_relation(), create_estate_for_relation(), EvalPlanQualStart(), evaluate_expr(), ExecuteCallStmt(), ExecuteQuery(), ExecuteTruncateGuts(), ExplainExecuteQuery(), fileIterateForeignScan(), 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(), and validateDomainConstraint().

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 304 of file execUtils.c.

305 {
307 }
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: execUtils.c:234

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 355 of file execUtils.c.

356 {
357  ExprContext *econtext;
358 
359  /* Create the ExprContext node within the caller's memory context */
360  econtext = makeNode(ExprContext);
361 
362  /* Initialize fields of ExprContext */
363  econtext->ecxt_scantuple = NULL;
364  econtext->ecxt_innertuple = NULL;
365  econtext->ecxt_outertuple = NULL;
366 
368 
369  /*
370  * Create working memory for expression evaluation in this context.
371  */
372  econtext->ecxt_per_tuple_memory =
374  "ExprContext",
376 
377  econtext->ecxt_param_exec_vals = NULL;
378  econtext->ecxt_param_list_info = NULL;
379 
380  econtext->ecxt_aggvalues = NULL;
381  econtext->ecxt_aggnulls = NULL;
382 
383  econtext->caseValue_datum = (Datum) 0;
384  econtext->caseValue_isNull = true;
385 
386  econtext->domainValue_datum = (Datum) 0;
387  econtext->domainValue_isNull = true;
388 
389  econtext->ecxt_estate = NULL;
390 
391  econtext->ecxt_callbacks = NULL;
392 
393  return econtext;
394 }
uintptr_t Datum
Definition: postgres.h:64
Datum domainValue_datum
Definition: execnodes.h:286
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:267
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:263
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:257
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:266
Datum * ecxt_aggvalues
Definition: execnodes.h:274
bool caseValue_isNull
Definition: execnodes.h:282
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:255
Datum caseValue_datum
Definition: execnodes.h:280
bool * ecxt_aggnulls
Definition: execnodes.h:276
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:262
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:294
bool domainValue_isNull
Definition: execnodes.h:288
struct EState * ecxt_estate
Definition: execnodes.h:291
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:259

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

◆ CreateWorkExprContext()

ExprContext* CreateWorkExprContext ( EState estate)

Definition at line 319 of file execUtils.c.

320 {
321  Size minContextSize = ALLOCSET_DEFAULT_MINSIZE;
322  Size initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
323  Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
324 
325  /* choose the maxBlockSize to be no larger than 1/16 of work_mem */
326  while (16 * maxBlockSize > work_mem * 1024L)
327  maxBlockSize >>= 1;
328 
329  if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
330  maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
331 
332  return CreateExprContextInternal(estate, minContextSize,
333  initBlockSize, maxBlockSize);
334 }
int work_mem
Definition: globals.c:128
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:152
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:150
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:151

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

Referenced by ExecInitAgg().

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 2302 of file execTuples.c.

2303 {
2304  Datum values[1];
2305  bool isnull[1] = {false};
2306 
2307  while (*txt)
2308  {
2309  const char *eol;
2310  int len;
2311 
2312  eol = strchr(txt, '\n');
2313  if (eol)
2314  {
2315  len = eol - txt;
2316  eol++;
2317  }
2318  else
2319  {
2320  len = strlen(txt);
2321  eol = txt + len;
2322  }
2323 
2325  do_tup_output(tstate, values, isnull);
2327  txt = eol;
2328  }
2329 }
void do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
Definition: execTuples.c:2274
void pfree(void *pointer)
Definition: mcxt.c:1508
const void size_t len
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

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

Referenced by ExplainQuery().

◆ do_tup_output()

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

Definition at line 2274 of file execTuples.c.

2275 {
2276  TupleTableSlot *slot = tstate->slot;
2277  int natts = slot->tts_tupleDescriptor->natts;
2278 
2279  /* make sure the slot is clear */
2280  ExecClearTuple(slot);
2281 
2282  /* insert data */
2283  memcpy(slot->tts_values, values, natts * sizeof(Datum));
2284  memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2285 
2286  /* mark slot as containing a virtual tuple */
2287  ExecStoreVirtualTuple(slot);
2288 
2289  /* send the tuple to the receiver */
2290  (void) tstate->dest->receiveSlot(slot, tstate->dest);
2291 
2292  /* clean up */
2293  ExecClearTuple(slot);
2294 }
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1551
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:123
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:117
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:433

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

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

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 2332 of file execTuples.c.

2333 {
2334  tstate->dest->rShutdown(tstate->dest);
2335  /* note that destroying the dest is not ours to do */
2337  pfree(tstate);
2338 }
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1253
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:123

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

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

◆ EvalPlanQual()

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

Definition at line 2468 of file execMain.c.

2470 {
2471  TupleTableSlot *slot;
2472  TupleTableSlot *testslot;
2473 
2474  Assert(rti > 0);
2475 
2476  /*
2477  * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2478  */
2479  EvalPlanQualBegin(epqstate);
2480 
2481  /*
2482  * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
2483  * an unnecessary copy.
2484  */
2485  testslot = EvalPlanQualSlot(epqstate, relation, rti);
2486  if (testslot != inputslot)
2487  ExecCopySlot(testslot, inputslot);
2488 
2489  /*
2490  * Mark that an EPQ tuple is available for this relation. (If there is
2491  * more than one result relation, the others remain marked as having no
2492  * tuple available.)
2493  */
2494  epqstate->relsubs_done[rti - 1] = false;
2495  epqstate->relsubs_blocked[rti - 1] = false;
2496 
2497  /*
2498  * Run the EPQ query. We assume it will return at most one tuple.
2499  */
2500  slot = EvalPlanQualNext(epqstate);
2501 
2502  /*
2503  * If we got a tuple, force the slot to materialize the tuple so that it
2504  * is not dependent on any local state in the EPQ query (in particular,
2505  * it's highly likely that the slot contains references to any pass-by-ref
2506  * datums that may be present in copyTuple). As with the next step, this
2507  * is to guard against early re-use of the EPQ query.
2508  */
2509  if (!TupIsNull(slot))
2510  ExecMaterializeSlot(slot);
2511 
2512  /*
2513  * Clear out the test tuple, and mark that no tuple is available here.
2514  * This is needed in case the EPQ state is re-used to test a tuple for a
2515  * different target relation.
2516  */
2517  ExecClearTuple(testslot);
2518  epqstate->relsubs_blocked[rti - 1] = true;
2519 
2520  return slot;
2521 }
void EvalPlanQualBegin(EPQState *epqstate)
Definition: execMain.c:2749
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition: execMain.c:2733
TupleTableSlot * EvalPlanQualSlot(EPQState *epqstate, Relation relation, Index rti)
Definition: execMain.c:2596
bool * relsubs_blocked
Definition: execnodes.h:1234
bool * relsubs_done
Definition: execnodes.h:1225
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:488
#define TupIsNull(slot)
Definition: tuptable.h:300
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:451

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2749 of file execMain.c.

2750 {
2751  EState *parentestate = epqstate->parentestate;
2752  EState *recheckestate = epqstate->recheckestate;
2753 
2754  if (recheckestate == NULL)
2755  {
2756  /* First time through, so create a child EState */
2757  EvalPlanQualStart(epqstate, epqstate->plan);
2758  }
2759  else
2760  {
2761  /*
2762  * We already have a suitable child EPQ tree, so just reset it.
2763  */
2764  Index rtsize = parentestate->es_range_table_size;
2765  PlanState *rcplanstate = epqstate->recheckplanstate;
2766 
2767  /*
2768  * Reset the relsubs_done[] flags to equal relsubs_blocked[], so that
2769  * the EPQ run will never attempt to fetch tuples from blocked target
2770  * relations.
2771  */
2772  memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
2773  rtsize * sizeof(bool));
2774 
2775  /* Recopy current values of parent parameters */
2776  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2777  {
2778  int i;
2779 
2780  /*
2781  * Force evaluation of any InitPlan outputs that could be needed
2782  * by the subplan, just in case they got reset since
2783  * EvalPlanQualStart (see comments therein).
2784  */
2785  ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2786  GetPerTupleExprContext(parentestate));
2787 
2788  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2789 
2790  while (--i >= 0)
2791  {
2792  /* copy value if any, but not execPlan link */
2793  recheckestate->es_param_exec_vals[i].value =
2794  parentestate->es_param_exec_vals[i].value;
2795  recheckestate->es_param_exec_vals[i].isnull =
2796  parentestate->es_param_exec_vals[i].isnull;
2797  }
2798  }
2799 
2800  /*
2801  * Mark child plan tree as needing rescan at all scan nodes. The
2802  * first ExecProcNode will take care of actually doing the rescan.
2803  */
2804  rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2805  epqstate->epqParam);
2806  }
2807 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
unsigned int Index
Definition: c.h:601
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition: execMain.c:2816
#define GetPerTupleExprContext(estate)
Definition: executor.h:550
int i
Definition: isn.c:73
void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext)
Definition: nodeSubplan.c:1268
static int list_length(const List *l)
Definition: pg_list.h:152
Plan * plan
Definition: execnodes.h:1197
int epqParam
Definition: execnodes.h:1180
EState * parentestate
Definition: execnodes.h:1179
EState * recheckestate
Definition: execnodes.h:1211
PlanState * recheckplanstate
Definition: execnodes.h:1236
bool isnull
Definition: params.h:150
Datum value
Definition: params.h:149
Plan * plan
Definition: execnodes.h:1043
Bitmapset * chgParam
Definition: execnodes.h:1075
Bitmapset * extParam
Definition: plannodes.h:170
List * paramExecTypes
Definition: plannodes.h:93

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

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2980 of file execMain.c.

2981 {
2982  EState *estate = epqstate->recheckestate;
2983  Index rtsize;
2984  MemoryContext oldcontext;
2985  ListCell *l;
2986 
2987  rtsize = epqstate->parentestate->es_range_table_size;
2988 
2989  /*
2990  * We may have a tuple table, even if EPQ wasn't started, because we allow
2991  * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
2992  */
2993  if (epqstate->tuple_table != NIL)
2994  {
2995  memset(epqstate->relsubs_slot, 0,
2996  rtsize * sizeof(TupleTableSlot *));
2997  ExecResetTupleTable(epqstate->tuple_table, true);
2998  epqstate->tuple_table = NIL;
2999  }
3000 
3001  /* EPQ wasn't started, nothing further to do */
3002  if (estate == NULL)
3003  return;
3004 
3005  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3006 
3007  ExecEndNode(epqstate->recheckplanstate);
3008 
3009  foreach(l, estate->es_subplanstates)
3010  {
3011  PlanState *subplanstate = (PlanState *) lfirst(l);
3012 
3013  ExecEndNode(subplanstate);
3014  }
3015 
3016  /* throw away the per-estate tuple table, some node may have used it */
3017  ExecResetTupleTable(estate->es_tupleTable, false);
3018 
3019  /* Close any result and trigger target relations attached to this EState */
3020  ExecCloseResultRelations(estate);
3021 
3022  MemoryContextSwitchTo(oldcontext);
3023 
3024  FreeExecutorState(estate);
3025 
3026  /* Mark EPQState idle */
3027  epqstate->origslot = NULL;
3028  epqstate->recheckestate = NULL;
3029  epqstate->recheckplanstate = NULL;
3030  epqstate->relsubs_rowmark = NULL;
3031  epqstate->relsubs_done = NULL;
3032  epqstate->relsubs_blocked = NULL;
3033 }
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1515
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1190
void FreeExecutorState(EState *estate)
Definition: execUtils.c:189
#define lfirst(lc)
Definition: pg_list.h:172
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1218
TupleTableSlot * origslot
Definition: execnodes.h:1206
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1190
List * tuple_table
Definition: execnodes.h:1189

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

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

◆ EvalPlanQualFetchRowMark()

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

Definition at line 2624 of file execMain.c.

2625 {
2626  ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1];
2627  ExecRowMark *erm = earm->rowmark;
2628  Datum datum;
2629  bool isNull;
2630 
2631  Assert(earm != NULL);
2632  Assert(epqstate->origslot != NULL);
2633 
2635  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2636 
2637  /* if child rel, must check whether it produced this row */
2638  if (erm->rti != erm->prti)
2639  {
2640  Oid tableoid;
2641 
2642  datum = ExecGetJunkAttribute(epqstate->origslot,
2643  earm->toidAttNo,
2644  &isNull);
2645  /* non-locked rels could be on the inside of outer joins */
2646  if (isNull)
2647  return false;
2648 
2649  tableoid = DatumGetObjectId(datum);
2650 
2651  Assert(OidIsValid(erm->relid));
2652  if (tableoid != erm->relid)
2653  {
2654  /* this child is inactive right now */
2655  return false;
2656  }
2657  }
2658 
2659  if (erm->markType == ROW_MARK_REFERENCE)
2660  {
2661  Assert(erm->relation != NULL);
2662 
2663  /* fetch the tuple's ctid */
2664  datum = ExecGetJunkAttribute(epqstate->origslot,
2665  earm->ctidAttNo,
2666  &isNull);
2667  /* non-locked rels could be on the inside of outer joins */
2668  if (isNull)
2669  return false;
2670 
2671  /* fetch requests on foreign tables must be passed to their FDW */
2672  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2673  {
2674  FdwRoutine *fdwroutine;
2675  bool updated = false;
2676 
2677  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2678  /* this should have been checked already, but let's be safe */
2679  if (fdwroutine->RefetchForeignRow == NULL)
2680  ereport(ERROR,
2681  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2682  errmsg("cannot lock rows in foreign table \"%s\"",
2684 
2685  fdwroutine->RefetchForeignRow(epqstate->recheckestate,
2686  erm,
2687  datum,
2688  slot,
2689  &updated);
2690  if (TupIsNull(slot))
2691  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2692 
2693  /*
2694  * Ideally we'd insist on updated == false here, but that assumes
2695  * that FDWs can track that exactly, which they might not be able
2696  * to. So just ignore the flag.
2697  */
2698  return true;
2699  }
2700  else
2701  {
2702  /* ordinary table, fetch the tuple */
2704  (ItemPointer) DatumGetPointer(datum),
2705  SnapshotAny, slot))
2706  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2707  return true;
2708  }
2709  }
2710  else
2711  {
2712  Assert(erm->markType == ROW_MARK_COPY);
2713 
2714  /* fetch the whole-row Var for the relation */
2715  datum = ExecGetJunkAttribute(epqstate->origslot,
2716  earm->wholeAttNo,
2717  &isNull);
2718  /* non-locked rels could be on the inside of outer joins */
2719  if (isNull)
2720  return false;
2721 
2722  ExecStoreHeapTupleDatum(datum, slot);
2723  return true;
2724  }
2725 }
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
Definition: execTuples.c:1605
static Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: executor.h:190
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:432
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:1335
@ ROW_MARK_COPY
Definition: plannodes.h:1332
@ ROW_MARK_REFERENCE
Definition: plannodes.h:1331
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
unsigned int Oid
Definition: postgres_ext.h:31
#define SnapshotAny
Definition: snapmgr.h:33
AttrNumber wholeAttNo
Definition: execnodes.h:774
ExecRowMark * rowmark
Definition: execnodes.h:771
AttrNumber toidAttNo
Definition: execnodes.h:773
AttrNumber ctidAttNo
Definition: execnodes.h:772
Index rti
Definition: execnodes.h:749
Index prti
Definition: execnodes.h:750
Relation relation
Definition: execnodes.h:747
RowMarkType markType
Definition: execnodes.h:752
RefetchForeignRow_function RefetchForeignRow
Definition: fdwapi.h:248
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
Definition: tableam.h:1278

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

Referenced by ExecScanFetch().

◆ EvalPlanQualInit()

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

Definition at line 2537 of file execMain.c.

2540 {
2541  Index rtsize = parentestate->es_range_table_size;
2542 
2543  /* initialize data not changing over EPQState's lifetime */
2544  epqstate->parentestate = parentestate;
2545  epqstate->epqParam = epqParam;
2546  epqstate->resultRelations = resultRelations;
2547 
2548  /*
2549  * Allocate space to reference a slot for each potential rti - do so now
2550  * rather than in EvalPlanQualBegin(), as done for other dynamically
2551  * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2552  * that *may* need EPQ later, without forcing the overhead of
2553  * EvalPlanQualBegin().
2554  */
2555  epqstate->tuple_table = NIL;
2556  epqstate->relsubs_slot = (TupleTableSlot **)
2557  palloc0(rtsize * sizeof(TupleTableSlot *));
2558 
2559  /* ... and remember data that EvalPlanQualBegin will need */
2560  epqstate->plan = subplan;
2561  epqstate->arowMarks = auxrowmarks;
2562 
2563  /* ... and mark the EPQ state inactive */
2564  epqstate->origslot = NULL;
2565  epqstate->recheckestate = NULL;
2566  epqstate->recheckplanstate = NULL;
2567  epqstate->relsubs_rowmark = NULL;
2568  epqstate->relsubs_done = NULL;
2569  epqstate->relsubs_blocked = NULL;
2570 }
void * palloc0(Size size)
Definition: mcxt.c:1334
List * resultRelations
Definition: execnodes.h:1181
List * arowMarks
Definition: execnodes.h:1198

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

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

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 2733 of file execMain.c.

2734 {
2735  MemoryContext oldcontext;
2736  TupleTableSlot *slot;
2737 
2738  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2739  slot = ExecProcNode(epqstate->recheckplanstate);
2740  MemoryContextSwitchTo(oldcontext);
2741 
2742  return slot;
2743 }
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:269

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

Referenced by EvalPlanQual(), and ExecLockRows().

◆ EvalPlanQualSetPlan()

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

Definition at line 2579 of file execMain.c.

2580 {
2581  /* If we have a live EPQ query, shut it down */
2582  EvalPlanQualEnd(epqstate);
2583  /* And set/change the plan pointer */
2584  epqstate->plan = subplan;
2585  /* The rowmarks depend on the plan, too */
2586  epqstate->arowMarks = auxrowmarks;
2587 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2980

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2596 of file execMain.c.

2598 {
2599  TupleTableSlot **slot;
2600 
2601  Assert(relation);
2602  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2603  slot = &epqstate->relsubs_slot[rti - 1];
2604 
2605  if (*slot == NULL)
2606  {
2607  MemoryContext oldcontext;
2608 
2609  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2610  *slot = table_slot_create(relation, &epqstate->tuple_table);
2611  MemoryContextSwitchTo(oldcontext);
2612  }
2613 
2614  return *slot;
2615 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91

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

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

◆ exec_rt_fetch()

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

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

Definition at line 538 of file execUtils.c.

540 {
541  planstate->ps_ProjInfo =
543  planstate->ps_ExprContext,
544  planstate->ps_ResultTupleSlot,
545  planstate,
546  inputDesc);
547 }
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:354
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1081
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1083
List * targetlist
Definition: plannodes.h:152

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

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 647 of file execUtils.c.

648 {
649  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
650 
651  ExecSetSlotDescriptor(slot, tupDesc);
652 }
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:1288

References ExecSetSlotDescriptor(), and ScanState::ss_ScanTupleSlot.

Referenced by ExecWorkTableScan().

◆ ExecBuildAggTrans()

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

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2398 of file execMain.c.

2399 {
2400  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2401  char resname[32];
2402 
2403  aerm->rowmark = erm;
2404 
2405  /* Look up the resjunk columns associated with this rowmark */
2406  if (erm->markType != ROW_MARK_COPY)
2407  {
2408  /* need ctid for all methods other than COPY */
2409  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2410  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2411  resname);
2412  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2413  elog(ERROR, "could not find junk %s column", resname);
2414  }
2415  else
2416  {
2417  /* need wholerow if COPY */
2418  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2419  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2420  resname);
2421  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2422  elog(ERROR, "could not find junk %s column", resname);
2423  }
2424 
2425  /* if child rel, need tableoid */
2426  if (erm->rti != erm->prti)
2427  {
2428  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2429  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2430  resname);
2431  if (!AttributeNumberIsValid(aerm->toidAttNo))
2432  elog(ERROR, "could not find junk %s column", resname);
2433  }
2434 
2435  return aerm;
2436 }
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:222
#define snprintf
Definition: port.h:238
Index rowmarkId
Definition: execnodes.h:751

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ 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 3922 of file execExpr.c.

3929 {
3931  ExprEvalStep scratch = {0};
3932  int maxatt = -1;
3933  List *adjust_jumps = NIL;
3934  ListCell *lc;
3935 
3936  /*
3937  * When no columns are actually compared, the result's always true. See
3938  * special case in ExecQual().
3939  */
3940  if (numCols == 0)
3941  return NULL;
3942 
3943  state->expr = NULL;
3944  state->flags = EEO_FLAG_IS_QUAL;
3945  state->parent = parent;
3946 
3947  scratch.resvalue = &state->resvalue;
3948  scratch.resnull = &state->resnull;
3949 
3950  /* compute max needed attribute */
3951  for (int natt = 0; natt < numCols; natt++)
3952  {
3953  int attno = keyColIdx[natt];
3954 
3955  if (attno > maxatt)
3956  maxatt = attno;
3957  }
3958  Assert(maxatt >= 0);
3959 
3960  /* push deform steps */
3961  scratch.opcode = EEOP_INNER_FETCHSOME;
3962  scratch.d.fetch.last_var = maxatt;
3963  scratch.d.fetch.fixed = false;
3964  scratch.d.fetch.known_desc = ldesc;
3965  scratch.d.fetch.kind = lops;
3966  if (ExecComputeSlotInfo(state, &scratch))
3967  ExprEvalPushStep(state, &scratch);
3968 
3969  scratch.opcode = EEOP_OUTER_FETCHSOME;
3970  scratch.d.fetch.last_var = maxatt;
3971  scratch.d.fetch.fixed = false;
3972  scratch.d.fetch.known_desc = rdesc;
3973  scratch.d.fetch.kind = rops;
3974  if (ExecComputeSlotInfo(state, &scratch))
3975  ExprEvalPushStep(state, &scratch);
3976 
3977  /*
3978  * Start comparing at the last field (least significant sort key). That's
3979  * the most likely to be different if we are dealing with sorted input.
3980  */
3981  for (int natt = numCols; --natt >= 0;)
3982  {
3983  int attno = keyColIdx[natt];
3984  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3985  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3986  Oid foid = eqfunctions[natt];
3987  Oid collid = collations[natt];
3988  FmgrInfo *finfo;
3989  FunctionCallInfo fcinfo;
3990  AclResult aclresult;
3991 
3992  /* Check permission to call function */
3993  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
3994  if (aclresult != ACLCHECK_OK)
3995  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3996 
3998 
3999  /* Set up the primary fmgr lookup information */
4000  finfo = palloc0(sizeof(FmgrInfo));
4001  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4002  fmgr_info(foid, finfo);
4003  fmgr_info_set_expr(NULL, finfo);
4004  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4005  collid, NULL, NULL);
4006 
4007  /* left arg */
4008  scratch.opcode = EEOP_INNER_VAR;
4009  scratch.d.var.attnum = attno - 1;
4010  scratch.d.var.vartype = latt->atttypid;
4011  scratch.resvalue = &fcinfo->args[0].value;
4012  scratch.resnull = &fcinfo->args[0].isnull;
4013  ExprEvalPushStep(state, &scratch);
4014 
4015  /* right arg */
4016  scratch.opcode = EEOP_OUTER_VAR;
4017  scratch.d.var.attnum = attno - 1;
4018  scratch.d.var.vartype = ratt->atttypid;
4019  scratch.resvalue = &fcinfo->args[1].value;
4020  scratch.resnull = &fcinfo->args[1].isnull;
4021  ExprEvalPushStep(state, &scratch);
4022 
4023  /* evaluate distinctness */
4024  scratch.opcode = EEOP_NOT_DISTINCT;
4025  scratch.d.func.finfo = finfo;
4026  scratch.d.func.fcinfo_data = fcinfo;
4027  scratch.d.func.fn_addr = finfo->fn_addr;
4028  scratch.d.func.nargs = 2;
4029  scratch.resvalue = &state->resvalue;
4030  scratch.resnull = &state->resnull;
4031  ExprEvalPushStep(state, &scratch);
4032 
4033  /* then emit EEOP_QUAL to detect if result is false (or null) */
4034  scratch.opcode = EEOP_QUAL;
4035  scratch.d.qualexpr.jumpdone = -1;
4036  scratch.resvalue = &state->resvalue;
4037  scratch.resnull = &state->resnull;
4038  ExprEvalPushStep(state, &scratch);
4039  adjust_jumps = lappend_int(adjust_jumps,
4040  state->steps_len - 1);
4041  }
4042 
4043  /* adjust jump targets */
4044  foreach(lc, adjust_jumps)
4045  {
4046  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4047 
4048  Assert(as->opcode == EEOP_QUAL);
4049  Assert(as->d.qualexpr.jumpdone == -1);
4050  as->d.qualexpr.jumpdone = state->steps_len;
4051  }
4052 
4053  scratch.resvalue = NULL;
4054  scratch.resnull = NULL;
4055  scratch.opcode = EEOP_DONE;
4056  ExprEvalPushStep(state, &scratch);
4057 
4059 
4060  return state;
4061 }
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2688
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3876
Oid collid
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2567
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2861
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:869
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:174
@ EEOP_INNER_VAR
Definition: execExpr.h:77
@ EEOP_DONE
Definition: execExpr.h:69
@ EEOP_QUAL
Definition: execExpr.h:135
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:72
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:73
@ EEOP_OUTER_VAR
Definition: execExpr.h:78
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:76
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
List * lappend_int(List *list, int datum)
Definition: list.c:357
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1586
Oid GetUserId(void)
Definition: miscinit.c:514
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
@ OBJECT_FUNCTION
Definition: parsenodes.h:2128
#define ACL_EXECUTE
Definition: parsenodes.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define lfirst_int(lc)
Definition: pg_list.h:173
struct ExprEvalStep::@51::@52 fetch
union ExprEvalStep::@51 d
intptr_t opcode
Definition: execExpr.h:278
struct ExprEvalStep::@51::@60 qualexpr
Datum * resvalue
Definition: execExpr.h:281
struct ExprEvalStep::@51::@53 var
bool * resnull
Definition: execExpr.h:282
struct ExprEvalStep::@51::@58 func
Definition: fmgr.h:57
PGFunction fn_addr
Definition: fmgr.h:58
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Definition: pg_list.h:54
Datum value
Definition: postgres.h:75
bool isnull
Definition: postgres.h:77
Definition: regguts.h:323
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert(), collid, 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(), ExprEvalPushStep(), ExprEvalStep::fetch, 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_aclcheck(), OBJECT_FUNCTION, ExprEvalStep::opcode, palloc0(), ExprEvalStep::qualexpr, ExprEvalStep::resnull, ExprEvalStep::resvalue, SizeForFunctionCallInfo, TupleDescAttr, NullableDatum::value, and ExprEvalStep::var.

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

◆ 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 4079 of file execExpr.c.

4086 {
4088  ExprEvalStep scratch = {0};
4089  int maxatt = list_length(param_exprs);
4090  List *adjust_jumps = NIL;
4091  ListCell *lc;
4092 
4093  state->expr = NULL;
4094  state->flags = EEO_FLAG_IS_QUAL;
4095  state->parent = parent;
4096 
4097  scratch.resvalue = &state->resvalue;
4098  scratch.resnull = &state->resnull;
4099 
4100  /* push deform steps */
4101  scratch.opcode = EEOP_INNER_FETCHSOME;
4102  scratch.d.fetch.last_var = maxatt;
4103  scratch.d.fetch.fixed = false;
4104  scratch.d.fetch.known_desc = desc;
4105  scratch.d.fetch.kind = lops;
4106  if (ExecComputeSlotInfo(state, &scratch))
4107  ExprEvalPushStep(state, &scratch);
4108 
4109  scratch.opcode = EEOP_OUTER_FETCHSOME;
4110  scratch.d.fetch.last_var = maxatt;
4111  scratch.d.fetch.fixed = false;
4112  scratch.d.fetch.known_desc = desc;
4113  scratch.d.fetch.kind = rops;
4114  if (ExecComputeSlotInfo(state, &scratch))
4115  ExprEvalPushStep(state, &scratch);
4116 
4117  for (int attno = 0; attno < maxatt; attno++)
4118  {
4119  Form_pg_attribute att = TupleDescAttr(desc, attno);
4120  Oid foid = eqfunctions[attno];
4121  Oid collid = collations[attno];
4122  FmgrInfo *finfo;
4123  FunctionCallInfo fcinfo;
4124  AclResult aclresult;
4125 
4126  /* Check permission to call function */
4127  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4128  if (aclresult != ACLCHECK_OK)
4129  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4130 
4132 
4133  /* Set up the primary fmgr lookup information */
4134  finfo = palloc0(sizeof(FmgrInfo));
4135  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4136  fmgr_info(foid, finfo);
4137  fmgr_info_set_expr(NULL, finfo);
4138  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4139  collid, NULL, NULL);
4140 
4141  /* left arg */
4142  scratch.opcode = EEOP_INNER_VAR;
4143  scratch.d.var.attnum = attno;
4144  scratch.d.var.vartype = att->atttypid;
4145  scratch.resvalue = &fcinfo->args[0].value;
4146  scratch.resnull = &fcinfo->args[0].isnull;
4147  ExprEvalPushStep(state, &scratch);
4148 
4149  /* right arg */
4150  scratch.opcode = EEOP_OUTER_VAR;
4151  scratch.d.var.attnum = attno;
4152  scratch.d.var.vartype = att->atttypid;
4153  scratch.resvalue = &fcinfo->args[1].value;
4154  scratch.resnull = &fcinfo->args[1].isnull;
4155  ExprEvalPushStep(state, &scratch);
4156 
4157  /* evaluate distinctness */
4158  scratch.opcode = EEOP_NOT_DISTINCT;
4159  scratch.d.func.finfo = finfo;
4160  scratch.d.func.fcinfo_data = fcinfo;
4161  scratch.d.func.fn_addr = finfo->fn_addr;
4162  scratch.d.func.nargs = 2;
4163  scratch.resvalue = &state->resvalue;
4164  scratch.resnull = &state->resnull;
4165  ExprEvalPushStep(state, &scratch);
4166 
4167  /* then emit EEOP_QUAL to detect if result is false (or null) */
4168  scratch.opcode = EEOP_QUAL;
4169  scratch.d.qualexpr.jumpdone = -1;
4170  scratch.resvalue = &state->resvalue;
4171  scratch.resnull = &state->resnull;
4172  ExprEvalPushStep(state, &scratch);
4173  adjust_jumps = lappend_int(adjust_jumps,
4174  state->steps_len - 1);
4175  }
4176 
4177  /* adjust jump targets */
4178  foreach(lc, adjust_jumps)
4179  {
4180  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4181 
4182  Assert(as->opcode == EEOP_QUAL);
4183  Assert(as->d.qualexpr.jumpdone == -1);
4184  as->d.qualexpr.jumpdone = state->steps_len;
4185  }
4186 
4187  scratch.resvalue = NULL;
4188  scratch.resnull = NULL;
4189  scratch.opcode = EEOP_DONE;
4190  ExprEvalPushStep(state, &scratch);
4191 
4193 
4194  return state;
4195 }

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert(), collid, 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(), ExprEvalPushStep(), ExprEvalStep::fetch, 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_aclcheck(), OBJECT_FUNCTION, ExprEvalStep::opcode, palloc0(), ExprEvalStep::qualexpr, ExprEvalStep::resnull, ExprEvalStep::resvalue, SizeForFunctionCallInfo, TupleDescAttr, NullableDatum::value, and ExprEvalStep::var.

Referenced by ExecInitMemoize().

◆ ExecBuildProjectionInfo()

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

Definition at line 354 of file execExpr.c.

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

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, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), TargetEntry::expr, ExprEvalPushStep(), exprType(), get_typlen(), if(), INNER_VAR, IsA, lfirst_node, makeNode, ExprEvalStep::opcode, OUTER_VAR, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TargetEntry::resno, TupleDescAttr, and ExprState::type.

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

◆ ExecBuildUpdateProjection()

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

Definition at line 514 of file execExpr.c.

521 {
523  ExprState *state;
524  int nAssignableCols;
525  bool sawJunk;
526  Bitmapset *assignedCols;
527  ExprSetupInfo deform = {0, 0, 0, NIL};
528  ExprEvalStep scratch = {0};
529  int outerattnum;
530  ListCell *lc,
531  *lc2;
532 
533  projInfo->pi_exprContext = econtext;
534  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
535  projInfo->pi_state.type = T_ExprState;
536  state = &projInfo->pi_state;
537  if (evalTargetList)
538  state->expr = (Expr *) targetList;
539  else
540  state->expr = NULL; /* not used */
541  state->parent = parent;
542  state->ext_params = NULL;
543 
544  state->resultslot = slot;
545 
546  /*
547  * Examine the targetList to see how many non-junk columns there are, and
548  * to verify that the non-junk columns come before the junk ones.
549  */
550  nAssignableCols = 0;
551  sawJunk = false;
552  foreach(lc, targetList)
553  {
554  TargetEntry *tle = lfirst_node(TargetEntry, lc);
555 
556  if (tle->resjunk)
557  sawJunk = true;
558  else
559  {
560  if (sawJunk)
561  elog(ERROR, "subplan target list is out of order");
562  nAssignableCols++;
563  }
564  }
565 
566  /* We should have one targetColnos entry per non-junk column */
567  if (nAssignableCols != list_length(targetColnos))
568  elog(ERROR, "targetColnos does not match subplan target list");
569 
570  /*
571  * Build a bitmapset of the columns in targetColnos. (We could just use
572  * list_member_int() tests, but that risks O(N^2) behavior with many
573  * columns.)
574  */
575  assignedCols = NULL;
576  foreach(lc, targetColnos)
577  {
578  AttrNumber targetattnum = lfirst_int(lc);
579 
580  assignedCols = bms_add_member(assignedCols, targetattnum);
581  }
582 
583  /*
584  * We need to insert EEOP_*_FETCHSOME steps to ensure the input tuples are
585  * sufficiently deconstructed. The scan tuple must be deconstructed at
586  * least as far as the last old column we need.
587  */
588  for (int attnum = relDesc->natts; attnum > 0; attnum--)
589  {
590  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
591 
592  if (attr->attisdropped)
593  continue;
594  if (bms_is_member(attnum, assignedCols))
595  continue;
596  deform.last_scan = attnum;
597  break;
598  }
599 
600  /*
601  * If we're actually evaluating the tlist, incorporate its input
602  * requirements too; otherwise, we'll just need to fetch the appropriate
603  * number of columns of the "outer" tuple.
604  */
605  if (evalTargetList)
606  expr_setup_walker((Node *) targetList, &deform);
607  else
608  deform.last_outer = nAssignableCols;
609 
610  ExecPushExprSetupSteps(state, &deform);
611 
612  /*
613  * Now generate code to evaluate the tlist's assignable expressions or
614  * fetch them from the outer tuple, incidentally validating that they'll
615  * be of the right data type. The checks above ensure that the forboth()
616  * will iterate over exactly the non-junk columns. Note that we don't
617  * bother evaluating any remaining resjunk columns.
618  */
619  outerattnum = 0;
620  forboth(lc, targetList, lc2, targetColnos)
621  {
622  TargetEntry *tle = lfirst_node(TargetEntry, lc);
623  AttrNumber targetattnum = lfirst_int(lc2);
624  Form_pg_attribute attr;
625 
626  Assert(!tle->resjunk);
627 
628  /*
629  * Apply sanity checks comparable to ExecCheckPlanOutput().
630  */
631  if (targetattnum <= 0 || targetattnum > relDesc->natts)
632  ereport(ERROR,
633  (errcode(ERRCODE_DATATYPE_MISMATCH),
634  errmsg("table row type and query-specified row type do not match"),
635  errdetail("Query has too many columns.")));
636  attr = TupleDescAttr(relDesc, targetattnum - 1);
637 
638  if (attr->attisdropped)
639  ereport(ERROR,
640  (errcode(ERRCODE_DATATYPE_MISMATCH),
641  errmsg("table row type and query-specified row type do not match"),
642  errdetail("Query provides a value for a dropped column at ordinal position %d.",
643  targetattnum)));
644  if (exprType((Node *) tle->expr) != attr->atttypid)
645  ereport(ERROR,
646  (errcode(ERRCODE_DATATYPE_MISMATCH),
647  errmsg("table row type and query-specified row type do not match"),
648  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
649  format_type_be(attr->atttypid),
650  targetattnum,
651  format_type_be(exprType((Node *) tle->expr)))));
652 
653  /* OK, generate code to perform the assignment. */
654  if (evalTargetList)
655  {
656  /*
657  * We must evaluate the TLE's expression and assign it. We do not
658  * bother jumping through hoops for "safe" Vars like
659  * ExecBuildProjectionInfo does; this is a relatively less-used
660  * path and it doesn't seem worth expending code for that.
661  */
662  ExecInitExprRec(tle->expr, state,
663  &state->resvalue, &state->resnull);
664  /* Needn't worry about read-only-ness here, either. */
665  scratch.opcode = EEOP_ASSIGN_TMP;
666  scratch.d.assign_tmp.resultnum = targetattnum - 1;
667  ExprEvalPushStep(state, &scratch);
668  }
669  else
670  {
671  /* Just assign from the outer tuple. */
672  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
673  scratch.d.assign_var.attnum = outerattnum;
674  scratch.d.assign_var.resultnum = targetattnum - 1;
675  ExprEvalPushStep(state, &scratch);
676  }
677  outerattnum++;
678  }
679 
680  /*
681  * Now generate code to copy over any old columns that were not assigned
682  * to, and to ensure that dropped columns are set to NULL.
683  */
684  for (int attnum = 1; attnum <= relDesc->natts; attnum++)
685  {
686  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
687 
688  if (attr->attisdropped)
689  {
690  /* Put a null into the ExprState's resvalue/resnull ... */
691  scratch.opcode = EEOP_CONST;
692  scratch.resvalue = &state->resvalue;
693  scratch.resnull = &state->resnull;
694  scratch.d.constval.value = (Datum) 0;
695  scratch.d.constval.isnull = true;
696  ExprEvalPushStep(state, &scratch);
697  /* ... then assign it to the result slot */
698  scratch.opcode = EEOP_ASSIGN_TMP;
699  scratch.d.assign_tmp.resultnum = attnum - 1;
700  ExprEvalPushStep(state, &scratch);
701  }
702  else if (!bms_is_member(attnum, assignedCols))
703  {
704  /* Certainly the right type, so needn't check */
705  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
706  scratch.d.assign_var.attnum = attnum - 1;
707  scratch.d.assign_var.resultnum = attnum - 1;
708  ExprEvalPushStep(state, &scratch);
709  }
710  }
711 
712  scratch.opcode = EEOP_DONE;
713  ExprEvalPushStep(state, &scratch);
714 
716 
717  return projInfo;
718 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
static void ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info)
Definition: execExpr.c:2714
static bool expr_setup_walker(Node *node, ExprSetupInfo *info)
Definition: execExpr.c:2797
@ EEOP_CONST
Definition: execExpr.h:104
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
struct ExprEvalStep::@51::@57 constval
AttrNumber last_scan
Definition: execExpr.c:60
AttrNumber last_outer
Definition: execExpr.c:59

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, ExecInitExprRec(), ExecPushExprSetupSteps(), ExecReadyExpr(), TargetEntry::expr, expr_setup_walker(), ExprEvalPushStep(), exprType(), forboth, format_type_be(), ExprSetupInfo::last_outer, ExprSetupInfo::last_scan, lfirst_int, lfirst_node, list_length(), makeNode, TupleDescData::natts, NIL, ExprEvalStep::opcode, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, ExprEvalStep::resnull, ExprEvalStep::resvalue, TupleDescAttr, and ExprState::type.

Referenced by ExecInitMerge(), ExecInitModifyTable(), ExecInitPartitionInfo(), and ExecInitUpdateProjection().

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)

Definition at line 839 of file execExpr.c.

840 {
841  Datum ret;
842  bool isnull;
843 
844  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
845  if (state == NULL)
846  return true;
847 
848  /* verify that expression was not compiled using ExecInitQual */
849  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
850 
851  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
852 
853  if (isnull)
854  return true;
855 
856  return DatumGetBool(ret);
857 }
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:348
static bool DatumGetBool(Datum X)
Definition: postgres.h:90

References Assert(), DatumGetBool(), EEO_FLAG_IS_QUAL, and ExecEvalExprSwitchContext().

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

◆ ExecCheckIndexConstraints()

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

Definition at line 527 of file execIndexing.c.

530 {
531  int i;
532  int numIndices;
533  RelationPtr relationDescs;
534  Relation heapRelation;
535  IndexInfo **indexInfoArray;
536  ExprContext *econtext;
538  bool isnull[INDEX_MAX_KEYS];
539  ItemPointerData invalidItemPtr;
540  bool checkedIndex = false;
541 
542  ItemPointerSetInvalid(conflictTid);
543  ItemPointerSetInvalid(&invalidItemPtr);
544 
545  /*
546  * Get information from the result relation info structure.
547  */
548  numIndices = resultRelInfo->ri_NumIndices;
549  relationDescs = resultRelInfo->ri_IndexRelationDescs;
550  indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
551  heapRelation = resultRelInfo->ri_RelationDesc;
552 
553  /*
554  * We will use the EState's per-tuple context for evaluating predicates
555  * and index expressions (creating it if it's not already there).
556  */
557  econtext = GetPerTupleExprContext(estate);
558 
559  /* Arrange for econtext's scan tuple to be the tuple under test */
560  econtext->ecxt_scantuple = slot;
561 
562  /*
563  * For each index, form index tuple and check if it satisfies the
564  * constraint.
565  */
566  for (i = 0; i < numIndices; i++)
567  {
568  Relation indexRelation = relationDescs[i];
569  IndexInfo *indexInfo;
570  bool satisfiesConstraint;
571 
572  if (indexRelation == NULL)
573  continue;
574 
575  indexInfo = indexInfoArray[i];
576 
577  if (!indexInfo->ii_Unique && !indexInfo->ii_ExclusionOps)
578  continue;
579 
580  /* If the index is marked as read-only, ignore it */
581  if (!indexInfo->ii_ReadyForInserts)
582  continue;
583 
584  /* When specific arbiter indexes requested, only examine them */
585  if (arbiterIndexes != NIL &&
586  !list_member_oid(arbiterIndexes,
587  indexRelation->rd_index->indexrelid))
588  continue;
589 
590  if (!indexRelation->rd_index->indimmediate)
591  ereport(ERROR,
592  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
593  errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),
594  errtableconstraint(heapRelation,
595  RelationGetRelationName(indexRelation))));
596 
597  checkedIndex = true;
598 
599  /* Check for partial index */
600  if (indexInfo->ii_Predicate != NIL)
601  {
602  ExprState *predicate;
603 
604  /*
605  * If predicate state not set up yet, create it (in the estate's
606  * per-query context)
607  */
608  predicate = indexInfo->ii_PredicateState;
609  if (predicate == NULL)
610  {
611  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
612  indexInfo->ii_PredicateState = predicate;
613  }
614 
615  /* Skip this index-update if the predicate isn't satisfied */
616  if (!ExecQual(predicate, econtext))
617  continue;
618  }
619 
620  /*
621  * FormIndexDatum fills in its values and isnull parameters with the
622  * appropriate values for the column(s) of the index.
623  */
624  FormIndexDatum(indexInfo,
625  slot,
626  estate,
627  values,
628  isnull);
629 
630  satisfiesConstraint =
631  check_exclusion_or_unique_constraint(heapRelation, indexRelation,
632  indexInfo, &invalidItemPtr,
633  values, isnull, estate, false,
634  CEOUC_WAIT, true,
635  conflictTid);
636  if (!satisfiesConstraint)
637  return false;
638  }
639 
640  if (arbiterIndexes != NIL && !checkedIndex)
641  elog(ERROR, "unexpected failure to find arbiter index");
642 
643  return true;
644 }
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:760
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:413
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:2705
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
#define INDEX_MAX_KEYS
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5988
bool ii_Unique
Definition: execnodes.h:197
ExprState * ii_PredicateState
Definition: execnodes.h:190
Oid * ii_ExclusionOps
Definition: execnodes.h:191
bool ii_ReadyForInserts
Definition: execnodes.h:199
List * ii_Predicate
Definition: execnodes.h:189
Form_pg_index rd_index
Definition: rel.h:192
int ri_NumIndices
Definition: execnodes.h:459
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:462
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:465

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, ItemPointerSetInvalid(), list_member_oid(), NIL, RelationData::rd_index, RelationGetRelationName, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, and values.

Referenced by ExecInsert().

◆ ExecCheckPermissions()

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

Definition at line 579 of file execMain.c.

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

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

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1119 of file execUtils.c.

1120 {
1121  int len = 0;
1122  ListCell *tl;
1123 
1124  foreach(tl, targetlist)
1125  {
1126  TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1127 
1128  if (!curTle->resjunk)
1129  len++;
1130  }
1131  return len;
1132 }

References len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 1949 of file execTuples.c.

1950 {
1951  return ExecTypeFromTLInternal(targetList, true);
1952 }
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
Definition: execTuples.c:1955

References ExecTypeFromTLInternal().

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 231 of file execIndexing.c.

232 {
233  int i;
234  int numIndices;
235  RelationPtr indexDescs;
236  IndexInfo **indexInfos;
237 
238  numIndices = resultRelInfo->ri_NumIndices;
239  indexDescs = resultRelInfo->ri_IndexRelationDescs;
240  indexInfos = resultRelInfo->ri_IndexRelationInfo;
241 
242  for (i = 0; i < numIndices; i++)
243  {
244  if (indexDescs[i] == NULL)
245  continue; /* shouldn't happen? */
246 
247  /* Give the index a chance to do some post-insert cleanup */
248  index_insert_cleanup(indexDescs[i], indexInfos[i]);
249 
250  /* Drop lock acquired by ExecOpenIndices */
251  index_close(indexDescs[i], RowExclusiveLock);
252  }
253 
254  /*
255  * XXX should free indexInfo array here too? Currently we assume that
256  * such stuff will be cleaned up automatically in FreeExecutorState.
257  */
258 }
void index_insert_cleanup(Relation indexRelation, IndexInfo *indexInfo)
Definition: indexam.c:241
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
#define RowExclusiveLock
Definition: lockdefs.h:38

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

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

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1575 of file execMain.c.

1576 {
1577  int i;
1578 
1579  for (i = 0; i < estate->es_range_table_size; i++)
1580  {
1581  if (estate->es_relations[i])
1582  table_close(estate->es_relations[i], NoLock);
1583  }
1584 }
#define NoLock
Definition: lockdefs.h:34
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126

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

Referenced by CopyFrom(), and ExecEndPlan().

◆ ExecCloseResultRelations()

void ExecCloseResultRelations ( EState estate)

Definition at line 1515 of file execMain.c.

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

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

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

◆ ExecConditionalAssignProjectionInfo()

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

Definition at line 558 of file execUtils.c.

560 {
561  if (tlist_matches_tupdesc(planstate,
562  planstate->plan->targetlist,
563  varno,
564  inputDesc))
565  {
566  planstate->ps_ProjInfo = NULL;
567  planstate->resultopsset = planstate->scanopsset;
568  planstate->resultopsfixed = planstate->scanopsfixed;
569  planstate->resultops = planstate->scanops;
570  }
571  else
572  {
573  if (!planstate->ps_ResultTupleSlot)
574  {
575  ExecInitResultSlot(planstate, &TTSOpsVirtual);
576  planstate->resultops = &TTSOpsVirtual;
577  planstate->resultopsfixed = true;
578  planstate->resultopsset = true;
579  }
580  ExecAssignProjectionInfo(planstate, inputDesc);
581  }
582 }
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1778
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
Definition: execUtils.c:585
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:538
const TupleTableSlotOps * resultops
Definition: execnodes.h:1120
bool resultopsset
Definition: execnodes.h:1128
const TupleTableSlotOps * scanops
Definition: execnodes.h:1117
bool scanopsset
Definition: execnodes.h:1125
bool scanopsfixed
Definition: execnodes.h:1121
bool resultopsfixed
Definition: execnodes.h:1124

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

◆ ExecConstraints()

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

Definition at line 1914 of file execMain.c.

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

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

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

◆ ExecCreateScanSlotFromOuterPlan()

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

Definition at line 659 of file execUtils.c.

662 {
664  TupleDesc tupDesc;
665 
666  outerPlan = outerPlanState(scanstate);
667  tupDesc = ExecGetResultType(outerPlan);
668 
669  ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
670 }
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1810
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:493
#define outerPlanState(node)
Definition: execnodes.h:1139
#define outerPlan(node)
Definition: plannodes.h:182

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

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

◆ execCurrentOf()

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

Definition at line 44 of file execCurrent.c.

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 }
static ScanState * search_plan_tree(PlanState *node, Oid table_oid, bool *pending_rescan)
Definition: execCurrent.c:314
static char * fetch_cursor_param_value(ExprContext *econtext, int paramId)
Definition: execCurrent.c:258
ItemPointerData * ItemPointer
Definition: itemptr.h:49
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition: itemptr.h:83
@ PORTAL_ONE_SELECT
Definition: portal.h:91
#define PortalIsValid(p)
Definition: portal.h:212
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
char * cursor_name
Definition: primnodes.h:1851
ItemPointerData curCtid
Definition: execnodes.h:756
ItemPointerData xs_heaptid
Definition: relscan.h:147
QueryDesc * queryDesc
Definition: portal.h:157
bool atEnd
Definition: portal.h:200
bool atStart
Definition: portal.h:199
PortalStrategy strategy
Definition: portal.h:146
EState * estate
Definition: execdesc.h:48
PlanState * planstate
Definition: execdesc.h:49
#define TableOidAttributeNumber
Definition: sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:410

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

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 557 of file execProcnode.c.

558 {
559  /*
560  * do nothing when we get to the end of a leaf on tree.
561  */
562  if (node == NULL)
563  return;
564 
565  /*
566  * Make sure there's enough stack available. Need to check here, in
567  * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
568  * guaranteed that ExecProcNode() is reached for all nodes.
569  */
571 
572  if (node->chgParam != NULL)
573  {
574  bms_free(node->chgParam);
575  node->chgParam = NULL;
576  }
577 
578  switch (nodeTag(node))
579  {
580  /*
581  * control nodes
582  */
583  case T_ResultState:
584  ExecEndResult((ResultState *) node);
585  break;
586 
587  case T_ProjectSetState:
589  break;
590 
591  case T_ModifyTableState:
593  break;
594 
595  case T_AppendState:
596  ExecEndAppend((AppendState *) node);
597  break;
598 
599  case T_MergeAppendState:
601  break;
602 
603  case T_RecursiveUnionState:
605  break;
606 
607  case T_BitmapAndState:
609  break;
610 
611  case T_BitmapOrState:
612  ExecEndBitmapOr((BitmapOrState *) node);
613  break;
614 
615  /*
616  * scan nodes
617  */
618  case T_SeqScanState:
619  ExecEndSeqScan((SeqScanState *) node);
620  break;
621 
622  case T_SampleScanState:
624  break;
625 
626  case T_GatherState:
627  ExecEndGather((GatherState *) node);
628  break;
629 
630  case T_GatherMergeState:
632  break;
633 
634  case T_IndexScanState:
636  break;
637 
638  case T_IndexOnlyScanState:
640  break;
641 
642  case T_BitmapIndexScanState:
644  break;
645 
646  case T_BitmapHeapScanState:
648  break;
649 
650  case T_TidScanState:
651  ExecEndTidScan((TidScanState *) node);
652  break;
653 
654  case T_TidRangeScanState:
656  break;
657 
658  case T_SubqueryScanState:
660  break;
661 
662  case T_FunctionScanState:
664  break;
665 
666  case T_TableFuncScanState:
668  break;
669 
670  case T_CteScanState:
671  ExecEndCteScan((CteScanState *) node);
672  break;
673 
674  case T_ForeignScanState:
676  break;
677 
678  case T_CustomScanState:
680  break;
681 
682  /*
683  * join nodes
684  */
685  case T_NestLoopState:
686  ExecEndNestLoop((NestLoopState *) node);
687  break;
688 
689  case T_MergeJoinState:
691  break;
692 
693  case T_HashJoinState:
694  ExecEndHashJoin((HashJoinState *) node);
695  break;
696 
697  /*
698  * materialization nodes
699  */
700  case T_MaterialState:
701  ExecEndMaterial((MaterialState *) node);
702  break;
703 
704  case T_SortState:
705  ExecEndSort((SortState *) node);
706  break;
707 
708  case T_IncrementalSortState:
710  break;
711 
712  case T_MemoizeState:
713  ExecEndMemoize((MemoizeState *) node);
714  break;
715 
716  case T_GroupState:
717  ExecEndGroup((GroupState *) node);
718  break;
719 
720  case T_AggState:
721  ExecEndAgg((AggState *) node);
722  break;
723 
724  case T_WindowAggState:
726  break;
727 
728  case T_UniqueState:
729  ExecEndUnique((UniqueState *) node);
730  break;
731 
732  case T_HashState:
733  ExecEndHash((HashState *) node);
734  break;
735 
736  case T_SetOpState:
737  ExecEndSetOp((SetOpState *) node);
738  break;
739 
740  case T_LockRowsState:
741  ExecEndLockRows((LockRowsState *) node);
742  break;
743 
744  case T_LimitState:
745  ExecEndLimit((LimitState *) node);
746  break;
747 
748  /* No clean up actions for these nodes. */
749  case T_ValuesScanState:
750  case T_NamedTuplestoreScanState:
751  case T_WorkTableScanState:
752  break;
753 
754  default:
755  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
756  break;
757  }
758 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
void ExecEndAgg(AggState *node)
Definition: nodeAgg.c:4304
void ExecEndAppend(AppendState *node)
Definition: nodeAppend.c:386
void ExecEndBitmapAnd(BitmapAndState *node)
void ExecEndBitmapHeapScan(BitmapHeapScanState *node)
void ExecEndBitmapIndexScan(BitmapIndexScanState *node)
void ExecEndBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:196
void ExecEndCteScan(CteScanState *node)
Definition: nodeCtescan.c:288
void ExecEndCustomScan(CustomScanState *node)
Definition: nodeCustom.c:125
void ExecEndForeignScan(ForeignScanState *node)
void ExecEndFunctionScan(FunctionScanState *node)
void ExecEndGatherMerge(GatherMergeState *node)
void ExecEndGather(GatherState *node)
Definition: nodeGather.c:244
void ExecEndGroup(GroupState *node)
Definition: nodeGroup.c:226
void ExecEndHash(HashState *node)
Definition: nodeHash.c:413
void ExecEndHashJoin(HashJoinState *node)
Definition: nodeHashjoin.c:858
void ExecEndIncrementalSort(IncrementalSortState *node)
void ExecEndIndexOnlyScan(IndexOnlyScanState *node)
void ExecEndIndexScan(IndexScanState *node)
void ExecEndLimit(LimitState *node)
Definition: nodeLimit.c:534
void ExecEndLockRows(LockRowsState *node)
Definition: nodeLockRows.c:385
void ExecEndMaterial(MaterialState *node)
Definition: nodeMaterial.c:240
void ExecEndMemoize(MemoizeState *node)
Definition: nodeMemoize.c:1079
void ExecEndMergeAppend(MergeAppendState *node)
void ExecEndMergeJoin(MergeJoinState *node)
void ExecEndModifyTable(ModifyTableState *node)
void ExecEndNestLoop(NestLoopState *node)
Definition: nodeNestloop.c:361
void ExecEndProjectSet(ProjectSetState *node)
void ExecEndRecursiveUnion(RecursiveUnionState *node)
void ExecEndResult(ResultState *node)
Definition: nodeResult.c:240
void ExecEndSampleScan(SampleScanState *node)
void ExecEndSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:184
void ExecEndSetOp(SetOpState *node)
Definition: nodeSetOp.c:583
void ExecEndSort(SortState *node)
Definition: nodeSort.c:301
void ExecEndSubqueryScan(SubqueryScanState *node)
void ExecEndTableFuncScan(TableFuncScanState *node)
void ExecEndTidRangeScan(TidRangeScanState *node)
void ExecEndTidScan(TidScanState *node)
Definition: nodeTidscan.c:470
void ExecEndUnique(UniqueState *node)
Definition: nodeUnique.c:168
void ExecEndWindowAgg(WindowAggState *node)
#define nodeTag(nodeptr)
Definition: nodes.h:133
void check_stack_depth(void)
Definition: postgres.c:3531

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(), ExecEndMemoize(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndProjectSet(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSampleScan(), ExecEndSeqScan(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndTableFuncScan(), ExecEndTidRangeScan(), ExecEndTidScan(), ExecEndUnique(), ExecEndWindowAgg(), and nodeTag.

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

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

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

◆ ExecFilterJunk()

TupleTableSlot* ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 247 of file execJunk.c.

248 {
249  TupleTableSlot *resultSlot;
250  AttrNumber *cleanMap;
251  TupleDesc cleanTupType;
252  int cleanLength;
253  int i;
254  Datum *values;
255  bool *isnull;
256  Datum *old_values;
257  bool *old_isnull;
258 
259  /*
260  * Extract all the values of the old tuple.
261  */
262  slot_getallattrs(slot);
263  old_values = slot->tts_values;
264  old_isnull = slot->tts_isnull;
265 
266  /*
267  * get info from the junk filter
268  */
269  cleanTupType = junkfilter->jf_cleanTupType;
270  cleanLength = cleanTupType->natts;
271  cleanMap = junkfilter->jf_cleanMap;
272  resultSlot = junkfilter->jf_resultSlot;
273 
274  /*
275  * Prepare to build a virtual result tuple.
276  */
277  ExecClearTuple(resultSlot);
278  values = resultSlot->tts_values;
279  isnull = resultSlot->tts_isnull;
280 
281  /*
282  * Transpose data into proper fields of the new tuple.
283  */
284  for (i = 0; i < cleanLength; i++)
285  {
286  int j = cleanMap[i];
287 
288  if (j == 0)
289  {
290  values[i] = (Datum) 0;
291  isnull[i] = true;
292  }
293  else
294  {
295  values[i] = old_values[j - 1];
296  isnull[i] = old_isnull[j - 1];
297  }
298  }
299 
300  /*
301  * And return the virtual tuple.
302  */
303  return ExecStoreVirtualTuple(resultSlot);
304 }
int j
Definition: isn.c:74
TupleDesc jf_cleanTupType
Definition: execnodes.h:395
TupleTableSlot * jf_resultSlot
Definition: execnodes.h:397
AttrNumber * jf_cleanMap
Definition: execnodes.h:396
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:362

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

Referenced by ExecEvalWholeRowVar(), ExecutePlan(), and sqlfunction_receive().

◆ ExecFindJunkAttribute()

AttrNumber ExecFindJunkAttribute ( JunkFilter junkfilter,
const char *  attrName 
)

Definition at line 210 of file execJunk.c.

211 {
212  return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
213 }
List * jf_targetList
Definition: execnodes.h:394

References ExecFindJunkAttributeInTlist(), and JunkFilter::jf_targetList.

◆ ExecFindJunkAttributeInTlist()

AttrNumber ExecFindJunkAttributeInTlist ( List targetlist,
const char *  attrName 
)

Definition at line 222 of file execJunk.c.

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

References InvalidAttrNumber, lfirst, and TargetEntry::resno.

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

◆ ExecFindRowMark()

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

Definition at line 2375 of file execMain.c.

2376 {
2377  if (rti > 0 && rti <= estate->es_range_table_size &&
2378  estate->es_rowmarks != NULL)
2379  {
2380  ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2381 
2382  if (erm)
2383  return erm;
2384  }
2385  if (!missing_ok)
2386  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2387  return NULL;
2388 }

References elog, ERROR, and EState::es_rowmarks.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecGetAllUpdatedCols()

Bitmapset* ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1324 of file execUtils.c.

1325 {
1326  Bitmapset *ret;
1327  MemoryContext oldcxt;
1328 
1330 
1331  ret = bms_union(ExecGetUpdatedCols(relinfo, estate),
1332  ExecGetExtraUpdatedCols(relinfo, estate));
1333 
1334  MemoryContextSwitchTo(oldcxt);
1335 
1336  return ret;
1337 }
Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1309
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:555

References bms_union(), ExecGetExtraUpdatedCols(), ExecGetUpdatedCols(), GetPerTupleMemoryContext, and MemoryContextSwitchTo().

Referenced by ExecARUpdateTriggers(), ExecASUpdateTriggers(), ExecBRUpdateTriggers(), ExecBSUpdateTriggers(), and ExecUpdateLockMode().

◆ ExecGetAncestorResultRels()

List* ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1370 of file execMain.c.

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

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

Referenced by ExecCrossPartitionUpdateForeignKey().

◆ ExecGetChildToRootMap()

TupleConversionMap* ExecGetChildToRootMap ( ResultRelInfo resultRelInfo)

Definition at line 1206 of file execUtils.c.

1207 {
1208  /* If we didn't already do so, compute the map for this child. */
1209  if (!resultRelInfo->ri_ChildToRootMapValid)
1210  {
1211  ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1212 
1213  if (rootRelInfo)
1214  resultRelInfo->ri_ChildToRootMap =
1216  RelationGetDescr(rootRelInfo->ri_RelationDesc));
1217  else /* this isn't a child result rel */
1218  resultRelInfo->ri_ChildToRootMap = NULL;
1219 
1220  resultRelInfo->ri_ChildToRootMapValid = true;
1221  }
1222 
1223  return resultRelInfo->ri_ChildToRootMap;
1224 }
TupleConversionMap * ri_ChildToRootMap
Definition: execnodes.h:560
bool ri_ChildToRootMapValid
Definition: execnodes.h:561
TupleConversionMap * convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc)
Definition: tupconvert.c:102

References convert_tuples_by_name(), RelationGetDescr, ResultRelInfo::ri_ChildToRootMap, ResultRelInfo::ri_ChildToRootMapValid, ResultRelInfo::ri_RelationDesc, and ResultRelInfo::ri_RootResultRelInfo.

Referenced by adjust_partition_colnos(), AfterTriggerExecute(), AfterTriggerSaveEvent(), ExecCrossPartitionUpdate(), and TransitionTableAddTuple().

◆ ExecGetExtraUpdatedCols()

Bitmapset* ExecGetExtraUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1309 of file execUtils.c.

1310 {
1311  /* Compute the info if we didn't already */
1312  if (relinfo->ri_GeneratedExprsU == NULL)
1313  ExecInitStoredGenerated(relinfo, estate, CMD_UPDATE);
1314  return relinfo->ri_extraUpdatedCols;
1315 }
void ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype)
Bitmapset * ri_extraUpdatedCols
Definition: execnodes.h:474
ExprState ** ri_GeneratedExprsU
Definition: execnodes.h:529

References CMD_UPDATE, ExecInitStoredGenerated(), ResultRelInfo::ri_extraUpdatedCols, and ResultRelInfo::ri_GeneratedExprsU.

Referenced by ExecGetAllUpdatedCols(), and index_unchanged_by_update().

◆ ExecGetInsertedCols()

Bitmapset* ExecGetInsertedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1267 of file execUtils.c.

1268 {
1269  RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
1270 
1271  if (perminfo == NULL)
1272  return NULL;
1273 
1274  /* Map the columns to child's attribute numbers if needed. */
1275  if (relinfo->ri_RootResultRelInfo)
1276  {
1277  TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1278 
1279  if (map)
1280  return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
1281  }
1282 
1283  return perminfo->insertedCols;
1284 }
static RTEPermissionInfo * GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1344
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1232
Bitmapset * insertedCols
Definition: parsenodes.h:1253
AttrMap * attrMap
Definition: tupconvert.h:28
Bitmapset * execute_attr_map_cols(AttrMap *attrMap, Bitmapset *in_cols)
Definition: tupconvert.c:252

References TupleConversionMap::attrMap, ExecGetRootToChildMap(), execute_attr_map_cols(), GetResultRTEPermissionInfo(), RTEPermissionInfo::insertedCols, and ResultRelInfo::ri_RootResultRelInfo.

Referenced by ExecConstraints(), ExecPartitionCheckEmitError(), and ExecWithCheckOptions().

◆ ExecGetJunkAttribute()

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

Definition at line 190 of file executor.h.

191 {
192  Assert(attno > 0);
193  return slot_getattr(slot, attno, isNull);
194 }
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:389

References Assert(), and slot_getattr().

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

◆ ExecGetRangeTableRelation()

Relation ExecGetRangeTableRelation ( EState estate,
Index  rti 
)

Definition at line 762 of file execUtils.c.

763 {
764  Relation rel;
765 
766  Assert(rti > 0 && rti <= estate->es_range_table_size);
767 
768  rel = estate->es_relations[rti - 1];
769  if (rel == NULL)
770  {
771  /* First time through, so open the relation */
772  RangeTblEntry *rte = exec_rt_fetch(rti, estate);
773 
774  Assert(rte->rtekind == RTE_RELATION);
775 
776  if (!IsParallelWorker())
777  {
778  /*
779  * In a normal query, we should already have the appropriate lock,
780  * but verify that through an Assert. Since there's already an
781  * Assert inside table_open that insists on holding some lock, it
782  * seems sufficient to check this only when rellockmode is higher
783  * than the minimum.
784  */
785  rel = table_open(rte->relid, NoLock);
787  CheckRelationLockedByMe(rel, rte->rellockmode, false));
788  }
789  else
790  {
791  /*
792  * If we are a parallel worker, we need to obtain our own local
793  * lock on the relation. This ensures sane behavior in case the
794  * parent process exits before we do.
795  */
796  rel = table_open(rte->relid, rte->rellockmode);
797  }
798 
799  estate->es_relations[rti - 1] = rel;
800  }
801 
802  return rel;
803 }
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:587
#define IsParallelWorker()
Definition: parallel.h:60
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition: lmgr.c:330
#define AccessShareLock
Definition: lockdefs.h:36

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

Referenced by CreatePartitionPruneState(), ExecInitResultRelation(), ExecOpenScanRelation(), and InitPlan().

◆ ExecGetResultRelCheckAsUser()

Oid ExecGetResultRelCheckAsUser ( ResultRelInfo relInfo,
EState estate 
)

Definition at line 1395 of file execUtils.c.

1396 {
1397  RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relInfo, estate);
1398 
1399  /* XXX - maybe ok to return GetUserId() in this case? */
1400  if (perminfo == NULL)
1401  elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
1402  RelationGetRelid(relInfo->ri_RelationDesc));
1403 
1404  return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
1405 }

References RTEPermissionInfo::checkAsUser, elog, ERROR, GetResultRTEPermissionInfo(), GetUserId(), RelationGetRelid, and ResultRelInfo::ri_RelationDesc.

Referenced by create_foreign_modify().

◆ ExecGetResultSlotOps()

const TupleTableSlotOps* ExecGetResultSlotOps ( PlanState planstate,
bool isfixed 
)

Definition at line 502 of file execUtils.c.

503 {
504  if (planstate->resultopsset && planstate->resultops)
505  {
506  if (isfixed)
507  *isfixed = planstate->resultopsfixed;
508  return planstate->resultops;
509  }
510 
511  if (isfixed)
512  {
513  if (planstate->resultopsset)
514  *isfixed = planstate->resultopsfixed;
515  else if (planstate->ps_ResultTupleSlot)
516  *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
517  else
518  *isfixed = false;
519  }
520 
521  if (!planstate->ps_ResultTupleSlot)
522  return &TTSOpsVirtual;
523 
524  return planstate->ps_ResultTupleSlot->tts_ops;
525 }
const TupleTableSlotOps *const tts_ops
Definition: tuptable.h:121
#define TTS_FIXED(slot)
Definition: tuptable.h:108

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

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

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot* ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1182 of file execUtils.c.

1183 {
1184  if (relInfo->ri_ReturningSlot == NULL)
1185  {
1186  Relation rel = relInfo->ri_RelationDesc;
1187  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1188 
1189  relInfo->ri_ReturningSlot =
1190  ExecInitExtraTupleSlot(estate,
1191  RelationGetDescr(rel),
1192  table_slot_callbacks(rel));
1193 
1194  MemoryContextSwitchTo(oldcontext);
1195  }
1196 
1197  return relInfo->ri_ReturningSlot;
1198 }
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1830
TupleTableSlot * ri_ReturningSlot
Definition: execnodes.h:498
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:58

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

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

◆ ExecGetRootToChildMap()

TupleConversionMap* ExecGetRootToChildMap ( ResultRelInfo resultRelInfo,
EState estate 
)

Definition at line 1232 of file execUtils.c.

1233 {
1234  /* Mustn't get called for a non-child result relation. */
1235  Assert(resultRelInfo->ri_RootResultRelInfo);
1236 
1237  /* If we didn't already do so, compute the map for this child. */
1238  if (!resultRelInfo->ri_RootToChildMapValid)
1239  {
1240  ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1241  TupleDesc indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
1242  TupleDesc outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1243  Relation childrel = resultRelInfo->ri_RelationDesc;
1244  AttrMap *attrMap;
1245  MemoryContext oldcontext;
1246 
1247  /*
1248  * When this child table is not a partition (!relispartition), it may
1249  * have columns that are not present in the root table, which we ask
1250  * to ignore by passing true for missing_ok.
1251  */
1252  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1253  attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
1254  !childrel->rd_rel->relispartition);
1255  if (attrMap)
1256  resultRelInfo->ri_RootToChildMap =
1257  convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
1258  MemoryContextSwitchTo(oldcontext);
1259  resultRelInfo->ri_RootToChildMapValid = true;
1260  }
1261 
1262  return resultRelInfo->ri_RootToChildMap;
1263 }
TupleConversionMap * ri_RootToChildMap
Definition: execnodes.h:566
bool ri_RootToChildMapValid
Definition: execnodes.h:567
TupleConversionMap * convert_tuples_by_name_attrmap(TupleDesc indesc, TupleDesc outdesc, AttrMap *attrMap)
Definition: tupconvert.c:124

References Assert(), build_attrmap_by_name_if_req(), convert_tuples_by_name_attrmap(), EState::es_query_cxt, MemoryContextSwitchTo(), RelationData::rd_rel, RelationGetDescr, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, ResultRelInfo::ri_RootToChildMap, and ResultRelInfo::ri_RootToChildMapValid.

Referenced by apply_handle_tuple_routing(), CopyFrom(), ExecFindPartition(), ExecGetInsertedCols(), ExecGetUpdatedCols(), ExecInitPartitionInfo(), ExecInitRoutingInfo(), and ExecPrepareTupleRouting().

◆ ExecGetTriggerNewSlot()

TupleTableSlot* ExecGetTriggerNewSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1160 of file execUtils.c.

1161 {
1162  if (relInfo->ri_TrigNewSlot == NULL)
1163  {
1164  Relation rel = relInfo->ri_RelationDesc;
1165  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1166 
1167  relInfo->ri_TrigNewSlot =
1168  ExecInitExtraTupleSlot(estate,
1169  RelationGetDescr(rel),
1170  table_slot_callbacks(rel));
1171 
1172  MemoryContextSwitchTo(oldcontext);
1173  }
1174 
1175  return relInfo->ri_TrigNewSlot;
1176 }
TupleTableSlot * ri_TrigNewSlot
Definition: execnodes.h:500

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

Referenced by AfterTriggerExecute(), and AfterTriggerSaveEvent().

◆ ExecGetTriggerOldSlot()

TupleTableSlot* ExecGetTriggerOldSlot ( EState estate,
ResultRelInfo relInfo 
)

◆ ExecGetTriggerResultRel()

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

Definition at line 1294 of file execMain.c.

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

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

Referenced by afterTriggerInvokeEvents().

◆ ExecGetUpdatedCols()

Bitmapset* ExecGetUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1288 of file execUtils.c.

1289 {
1290  RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
1291 
1292  if (perminfo == NULL)
1293  return NULL;
1294 
1295  /* Map the columns to child's attribute numbers if needed. */
1296  if (relinfo->ri_RootResultRelInfo)
1297  {
1298  TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1299 
1300  if (map)
1301  return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
1302  }
1303 
1304  return perminfo->updatedCols;
1305 }
Bitmapset * updatedCols
Definition: parsenodes.h:1254

References TupleConversionMap::attrMap, ExecGetRootToChildMap(), execute_attr_map_cols(), GetResultRTEPermissionInfo(), ResultRelInfo::ri_RootResultRelInfo, and RTEPermissionInfo::updatedCols.

Referenced by ExecConstraints(), ExecGetAllUpdatedCols(), ExecInitStoredGenerated(), ExecPartitionCheckEmitError(), ExecWithCheckOptions(), and index_unchanged_by_update().

◆ ExecGetUpdateNewTuple()

TupleTableSlot* ExecGetUpdateNewTuple ( ResultRelInfo relinfo,
TupleTableSlot planSlot,
TupleTableSlot oldSlot 
)

Definition at line 709 of file nodeModifyTable.c.

712 {
713  ProjectionInfo *newProj = relinfo->ri_projectNew;
714  ExprContext *econtext;
715 
716  /* Use a few extra Asserts to protect against outside callers */
717  Assert(relinfo->ri_projectNewInfoValid);
718  Assert(planSlot != NULL && !TTS_EMPTY(planSlot));
719  Assert(oldSlot != NULL && !TTS_EMPTY(oldSlot));
720 
721  econtext = newProj->pi_exprContext;
722  econtext->ecxt_outertuple = planSlot;
723  econtext->ecxt_scantuple = oldSlot;
724  return ExecProject(newProj);
725 }
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: executor.h:376
bool ri_projectNewInfoValid
Definition: execnodes.h:483
ProjectionInfo * ri_projectNew
Definition: execnodes.h:477
#define TTS_EMPTY(slot)
Definition: tuptable.h:96

References Assert(), ExprContext::ecxt_outertuple, ExprContext::ecxt_scantuple, ExecProject(), ProjectionInfo::pi_exprContext, ResultRelInfo::ri_projectNew, ResultRelInfo::ri_projectNewInfoValid, and TTS_EMPTY.

Referenced by ExecBRUpdateTriggers(), ExecCrossPartitionUpdate(), ExecModifyTable(), and ExecUpdate().

◆ ExecInitCheck()

ExprState* ExecInitCheck ( List qual,
PlanState parent 
)

Definition at line 299 of file execExpr.c.

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

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

Referenced by ExecPrepareCheck().

◆ ExecInitExpr()

ExprState* ExecInitExpr ( Expr node,
PlanState parent 
)

Definition at line 127 of file execExpr.c.

128 {
129  ExprState *state;
130  ExprEvalStep scratch = {0};
131 
132  /* Special case: NULL expression produces a NULL ExprState pointer */
133  if (node == NULL)
134  return NULL;
135 
136  /* Initialize ExprState with empty step list */
138  state->expr = node;
139  state->parent = parent;
140  state->ext_params = NULL;
141 
142  /* Insert setup steps as needed */
144 
145  /* Compile the expression proper */
146  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
147 
148  /* Finally, append a DONE step */
149  scratch.opcode = EEOP_DONE;
150  ExprEvalPushStep(state, &scratch);
151 
153 
154  return state;
155 }

References EEOP_DONE, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), makeNode, and ExprEvalStep::opcode.

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

◆ ExecInitExprList()

List* ExecInitExprList ( List nodes,
PlanState parent 
)

Definition at line 319 of file execExpr.c.

320 {
321  List *result = NIL;
322  ListCell *lc;
323 
324  foreach(lc, nodes)
325  {
326  Expr *e = lfirst(lc);
327 
328  result = lappend(result, ExecInitExpr(e, parent));
329  }
330 
331  return result;
332 }
e
Definition: preproc-init.c:82

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

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

◆ ExecInitExprWithParams()

ExprState* ExecInitExprWithParams ( Expr node,
ParamListInfo  ext_params 
)

Definition at line 164 of file execExpr.c.

165 {
166  ExprState *state;
167  ExprEvalStep scratch = {0};
168 
169  /* Special case: NULL expression produces a NULL ExprState pointer */
170  if (node == NULL)
171  return NULL;
172 
173  /* Initialize ExprState with empty step list */
175  state->expr = node;
176  state->parent = NULL;
177  state->ext_params = ext_params;
178 
179  /* Insert setup steps as needed */
181 
182  /* Compile the expression proper */
183  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
184 
185  /* Finally, append a DONE step */
186  scratch.opcode = EEOP_DONE;
187  ExprEvalPushStep(state, &scratch);
188 
190 
191  return state;
192 }

References EEOP_DONE, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), makeNode, and ExprEvalStep::opcode.

Referenced by exec_eval_simple_expr(), and InitPartitionPruneContext().

◆ ExecInitExtraTupleSlot()

TupleTableSlot* ExecInitExtraTupleSlot ( EState estate,
TupleDesc  tupledesc,
const TupleTableSlotOps tts_ops 
)

◆ ExecInitFunctionResultSet()

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

Definition at line 444 of file execSRF.c.

446 {
448 
449  state->funcReturnsSet = true;
450  state->expr = expr;
451  state->func.fn_oid = InvalidOid;
452 
453  /*
454  * Initialize metadata. The expression node could be either a FuncExpr or
455  * an OpExpr.
456  */
457  if (IsA(expr, FuncExpr))
458  {
459  FuncExpr *func = (FuncExpr *) expr;
460 
461  state->args = ExecInitExprList(func->args, parent);
462  init_sexpr(func->funcid, func->inputcollid, expr, state, parent,
463  econtext->ecxt_per_query_memory, true, true);
464  }
465  else if (IsA(expr, OpExpr))
466  {
467  OpExpr *op = (OpExpr *) expr;
468 
469  state->args = ExecInitExprList(op->args, parent);
470  init_sexpr(op->opfuncid, op->inputcollid, expr, state, parent,
471  econtext->ecxt_per_query_memory, true, true);
472  }
473  else
474  elog(ERROR, "unrecognized node type: %d",
475  (int) nodeTag(expr));
476 
477  /* shouldn't get here unless the selected function returns set */
478  Assert(state->func.fn_retset);
479 
480  return state;
481 }
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:319
static void init_sexpr(Oid foid, Oid input_collation, Expr *node, SetExprState *sexpr, PlanState *parent, MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF)
Definition: execSRF.c:696
#define InvalidOid
Definition: postgres_ext.h:36
Oid funcid
Definition: primnodes.h:706
List * args
Definition: primnodes.h:724
List * args
Definition: primnodes.h:792

References FuncExpr::args, OpExpr::args, Assert(), ExprContext::ecxt_per_query_memory, elog, ERROR, ExecInitExprList(), FuncExpr::funcid, init_sexpr(), InvalidOid, IsA, makeNode, and nodeTag.

Referenced by ExecInitProjectSet().

◆ ExecInitJunkFilter()

JunkFilter* ExecInitJunkFilter ( List targetList,
TupleTableSlot slot 
)

Definition at line 60 of file execJunk.c.

61 {
62  JunkFilter *junkfilter;
63  TupleDesc cleanTupType;
64  int cleanLength;
65  AttrNumber *cleanMap;
66 
67  /*
68  * Compute the tuple descriptor for the cleaned tuple.
69  */
70  cleanTupType = ExecCleanTypeFromTL(targetList);
71 
72  /*
73  * Use the given slot, or make a new slot if we weren't given one.
74  */
75  if (slot)
76  ExecSetSlotDescriptor(slot, cleanTupType);
77  else
78  slot = MakeSingleTupleTableSlot(cleanTupType, &TTSOpsVirtual);
79 
80  /*
81  * Now calculate the mapping between the original tuple's attributes and
82  * the "clean" tuple's attributes.
83  *
84  * The "map" is an array of "cleanLength" attribute numbers, i.e. one
85  * entry for every attribute of the "clean" tuple. The value of this entry
86  * is the attribute number of the corresponding attribute of the
87  * "original" tuple. (Zero indicates a NULL output attribute, but we do
88  * not use that feature in this routine.)
89  */
90  cleanLength = cleanTupType->natts;
91  if (cleanLength > 0)
92  {
93  AttrNumber cleanResno;
94  ListCell *t;
95 
96  cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
97  cleanResno = 0;
98  foreach(t, targetList)
99  {
100  TargetEntry *tle = lfirst(t);
101 
102  if (!tle->resjunk)
103  {
104  cleanMap[cleanResno] = tle->resno;
105  cleanResno++;
106  }
107  }
108  Assert(cleanResno == cleanLength);
109  }
110  else
111  cleanMap = NULL;
112 
113  /*
114  * Finally create and initialize the JunkFilter struct.
115  */
116  junkfilter = makeNode(JunkFilter);
117 
118  junkfilter->jf_targetList = targetList;
119  junkfilter->jf_cleanTupType = cleanTupType;
120  junkfilter->jf_cleanMap = cleanMap;
121  junkfilter->jf_resultSlot = slot;
122 
123  return junkfilter;
124 }
TupleDesc ExecCleanTypeFromTL(List *targetList)
Definition: execTuples.c:1949

References Assert(), ExecCleanTypeFromTL(), ExecSetSlotDescriptor(), JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, JunkFilter::jf_targetList, lfirst, makeNode, MakeSingleTupleTableSlot(), TupleDescData::natts, palloc(), TargetEntry::resno, and TTSOpsVirtual.

Referenced by ExecInitWholeRowVar(), init_sql_fcache(), and InitPlan().

◆ ExecInitJunkFilterConversion()

JunkFilter* ExecInitJunkFilterConversion ( List targetList,
TupleDesc  cleanTupType,
TupleTableSlot slot 
)

Definition at line 137 of file execJunk.c.

140 {
141  JunkFilter *junkfilter;
142  int cleanLength;
143  AttrNumber *cleanMap;
144  ListCell *t;
145  int i;
146 
147  /*
148  * Use the given slot, or make a new slot if we weren't given one.
149  */
150  if (slot)
151  ExecSetSlotDescriptor(slot, cleanTupType);
152  else
153  slot = MakeSingleTupleTableSlot(cleanTupType, &TTSOpsVirtual);
154 
155  /*
156  * Calculate the mapping between the original tuple's attributes and the
157  * "clean" tuple's attributes.
158  *
159  * The "map" is an array of "cleanLength" attribute numbers, i.e. one
160  * entry for every attribute of the "clean" tuple. The value of this entry
161  * is the attribute number of the corresponding attribute of the
162  * "original" tuple. We store zero for any deleted attributes, marking
163  * that a NULL is needed in the output tuple.
164  */
165  cleanLength = cleanTupType->natts;
166  if (cleanLength > 0)
167  {
168  cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
169  t = list_head(targetList);
170  for (i = 0; i < cleanLength; i++)
171  {
172  if (TupleDescAttr(cleanTupType, i)->attisdropped)
173  continue; /* map entry is already zero */
174  for (;;)
175  {
176  TargetEntry *tle = lfirst(t);
177 
178  t = lnext(targetList, t);
179  if (!tle->resjunk)
180  {
181  cleanMap[i] = tle->resno;
182  break;
183  }
184  }
185  }
186  }
187  else
188  cleanMap = NULL;
189 
190  /*
191  * Finally create and initialize the JunkFilter struct.
192  */
193  junkfilter = makeNode(JunkFilter);
194 
195  junkfilter->jf_targetList = targetList;
196  junkfilter->jf_cleanTupType = cleanTupType;
197  junkfilter->jf_cleanMap = cleanMap;
198  junkfilter->jf_resultSlot = slot;
199 
200  return junkfilter;
201 }
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

References ExecSetSlotDescriptor(), i, JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, JunkFilter::jf_targetList, lfirst, list_head(), lnext(), makeNode, MakeSingleTupleTableSlot(), TupleDescData::natts, palloc0(), TargetEntry::resno, TTSOpsVirtual, and TupleDescAttr.

Referenced by init_sql_fcache().

◆ ExecInitNode()

PlanState* ExecInitNode ( Plan node,
EState estate,
int  eflags 
)

Definition at line 142 of file execProcnode.c.

143 {
144  PlanState *result;
145  List *subps;
146  ListCell *l;
147 
148  /*
149  * do nothing when we get to the end of a leaf on tree.
150  */
151  if (node == NULL)
152  return NULL;
153 
154  /*
155  * Make sure there's enough stack available. Need to check here, in
156  * addition to ExecProcNode() (via ExecProcNodeFirst()), to ensure the
157  * stack isn't overrun while initializing the node tree.
158  */
160 
161  switch (nodeTag(node))
162  {
163  /*
164  * control nodes
165  */
166  case T_Result:
167  result = (PlanState *) ExecInitResult((Result *) node,
168  estate, eflags);
169  break;
170 
171  case T_ProjectSet:
172  result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
173  estate, eflags);
174  break;
175 
176  case T_ModifyTable:
177  result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
178  estate, eflags);
179  break;
180 
181  case T_Append:
182  result = (PlanState *) ExecInitAppend((Append *) node,
183  estate, eflags);
184  break;
185 
186  case T_MergeAppend:
187  result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
188  estate, eflags);
189  break;
190 
191  case T_RecursiveUnion:
192  result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
193  estate, eflags);
194  break;
195 
196  case T_BitmapAnd:
197  result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
198  estate, eflags);
199  break;
200 
201  case T_BitmapOr:
202  result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
203  estate, eflags);
204  break;
205 
206  /*
207  * scan nodes
208  */
209  case T_SeqScan:
210  result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
211  estate, eflags);
212  break;
213 
214  case T_SampleScan:
215  result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
216  estate, eflags);
217  break;
218 
219  case T_IndexScan:
220  result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
221  estate, eflags);
222  break;
223 
224  case T_IndexOnlyScan:
225  result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
226  estate, eflags);
227  break;
228 
229  case T_BitmapIndexScan:
230  result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
231  estate, eflags);
232  break;
233 
234  case T_BitmapHeapScan:
235  result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
236  estate, eflags);
237  break;
238 
239  case T_TidScan:
240  result = (PlanState *) ExecInitTidScan((TidScan *) node,
241  estate, eflags);
242  break;
243 
244  case T_TidRangeScan:
245  result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
246  estate, eflags);
247  break;
248 
249  case T_SubqueryScan:
250  result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
251  estate, eflags);
252  break;
253 
254  case T_FunctionScan:
255  result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
256  estate, eflags);
257  break;
258 
259  case T_TableFuncScan:
260  result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
261  estate, eflags);
262  break;
263 
264  case T_ValuesScan:
265  result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
266  estate, eflags);
267  break;
268 
269  case T_CteScan:
270  result = (PlanState *) ExecInitCteScan((CteScan *) node,
271  estate, eflags);
272  break;
273 
274  case T_NamedTuplestoreScan:
276  estate, eflags);
277  break;
278 
279  case T_WorkTableScan:
280  result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
281  estate, eflags);
282  break;
283 
284  case T_ForeignScan:
285  result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
286  estate, eflags);
287  break;
288 
289  case T_CustomScan:
290  result = (PlanState *) ExecInitCustomScan((CustomScan *) node,
291  estate, eflags);
292  break;
293 
294  /*
295  * join nodes
296  */
297  case T_NestLoop:
298  result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
299  estate, eflags);
300  break;
301 
302  case T_MergeJoin:
303  result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
304  estate, eflags);
305  break;
306 
307  case T_HashJoin:
308  result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
309  estate, eflags);
310  break;
311 
312  /*
313  * materialization nodes
314  */
315  case T_Material:
316  result = (PlanState *) ExecInitMaterial((Material *) node,
317  estate, eflags);
318  break;
319 
320  case T_Sort:
321  result = (PlanState *) ExecInitSort((Sort *) node,
322  estate, eflags);
323  break;
324 
325  case T_IncrementalSort:
326  result = (PlanState *) ExecInitIncrementalSort((IncrementalSort *) node,
327  estate, eflags);
328  break;
329 
330  case T_Memoize:
331  result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
332  eflags);
333  break;
334 
335  case T_Group:
336  result = (PlanState *) ExecInitGroup((Group *) node,
337  estate, eflags);
338  break;
339 
340  case T_Agg:
341  result = (PlanState *) ExecInitAgg((Agg *) node,
342  estate, eflags);
343  break;
344 
345  case T_WindowAgg:
346  result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
347  estate, eflags);
348  break;
349 
350  case T_Unique:
351  result = (PlanState *) ExecInitUnique((Unique *) node,
352  estate, eflags);
353  break;
354 
355  case T_Gather:
356  result = (PlanState *) ExecInitGather((Gather *) node,
357  estate, eflags);
358  break;
359 
360  case T_GatherMerge:
361  result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
362  estate, eflags);
363  break;
364 
365  case T_Hash:
366  result = (PlanState *) ExecInitHash((Hash *) node,
367  estate, eflags);
368  break;
369 
370  case T_SetOp:
371  result = (PlanState *) ExecInitSetOp((SetOp *) node,
372  estate, eflags);
373  break;
374 
375  case T_LockRows:
376  result = (PlanState *) ExecInitLockRows((LockRows *) node,
377  estate, eflags);
378  break;
379 
380  case T_Limit:
381  result = (PlanState *) ExecInitLimit((Limit *) node,
382  estate, eflags);
383  break;
384 
385  default:
386  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
387  result = NULL; /* keep compiler quiet */
388  break;
389  }
390 
391  ExecSetExecProcNode(result, result->ExecProcNode);
392 
393  /*
394  * Initialize any initPlans present in this node. The planner put them in
395  * a separate list for us.
396  */
397  subps = NIL;
398  foreach(l, node->initPlan)
399  {
400  SubPlan *subplan = (SubPlan *) lfirst(l);
401  SubPlanState *sstate;
402 
403  Assert(IsA(subplan, SubPlan));
404  sstate = ExecInitSubPlan(subplan, result);
405  subps = lappend(subps, sstate);
406  }
407  result->initPlan = subps;
408 
409  /* Set up instrumentation for this node if requested */
410  if (estate->es_instrument)
411  result->instrument = InstrAlloc(1, estate->es_instrument,
412  result->async_capable);
413 
414  return result;
415 }
void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
Definition: execProcnode.c:425
Instrumentation * InstrAlloc(int n, int instrument_options, bool async_mode)
Definition: instrument.c:31
AggState * ExecInitAgg(Agg *node, EState *estate, int eflags)
Definition: nodeAgg.c:3173
AppendState * ExecInitAppend(Append *node, EState *estate, int eflags)
Definition: nodeAppend.c:109
BitmapAndState * ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
Definition: nodeBitmapAnd.c:55
BitmapHeapScanState * ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
BitmapIndexScanState * ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
BitmapOrState * ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
Definition: nodeBitmapOr.c:56
CteScanState * ExecInitCteScan(CteScan *node, EState *estate, int eflags)
Definition: nodeCtescan.c:175
CustomScanState * ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
Definition: nodeCustom.c:26
ForeignScanState * ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
FunctionScanState * ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
GatherMergeState * ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
GatherState * ExecInitGather(Gather *node, EState *estate, int eflags)
Definition: nodeGather.c:53
GroupState * ExecInitGroup(Group *node, EState *estate, int eflags)
Definition: nodeGroup.c:161
HashState * ExecInitHash(Hash *node, EState *estate, int eflags)
Definition: nodeHash.c:360
HashJoinState * ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
Definition: nodeHashjoin.c:709
IncrementalSortState * ExecInitIncrementalSort(IncrementalSort *node, EState *estate, int eflags)
IndexOnlyScanState * ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
IndexScanState * ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
LimitState * ExecInitLimit(Limit *node, EState *estate, int eflags)
Definition: nodeLimit.c:447
LockRowsState * ExecInitLockRows(LockRows *node, EState *estate, int eflags)
Definition: nodeLockRows.c:291
MaterialState * ExecInitMaterial(Material *node, EState *estate, int eflags)
Definition: nodeMaterial.c:164
MemoizeState * ExecInitMemoize(Memoize *node, EState *estate, int eflags)
Definition: nodeMemoize.c:951
MergeAppendState * ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
MergeJoinState * ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
ModifyTableState * ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
NamedTuplestoreScanState * ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
NestLoopState * ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
Definition: nodeNestloop.c:262
ProjectSetState * ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
RecursiveUnionState * ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags)
ResultState * ExecInitResult(Result *node, EState *estate, int eflags)
Definition: nodeResult.c:180
SampleScanState * ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
SeqScanState * ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
Definition: nodeSeqscan.c:123
SetOpState * ExecInitSetOp(SetOp *node, EState *estate, int eflags)
Definition: nodeSetOp.c:481
SortState * ExecInitSort(Sort *node, EState *estate, int eflags)
Definition: nodeSort.c:221
SubPlanState * ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
Definition: nodeSubplan.c:823
SubqueryScanState * ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
TableFuncScanState * ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
TidRangeScanState * ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
TidScanState * ExecInitTidScan(TidScan *node, EState *estate, int eflags)
Definition: nodeTidscan.c:488
UniqueState * ExecInitUnique(Unique *node, EState *estate, int eflags)
Definition: nodeUnique.c:114
ValuesScanState * ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
WindowAggState * ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
WorkTableScanState * ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
Definition: plannodes.h:995
Instrumentation * instrument
Definition: execnodes.h:1053
List * initPlan
Definition: execnodes.h:1068
bool async_capable
Definition: execnodes.h:1085
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1049
List * initPlan
Definition: plannodes.h:156

References Assert(), PlanState::async_capable, check_stack_depth(), elog, ERROR, EState::es_instrument, ExecInitAgg(), ExecInitAppend(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapIndexScan(), ExecInitBitmapOr(), ExecInitCteScan(), ExecInitCustomScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGather(), ExecInitGatherMerge(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIncrementalSort(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMemoize(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNamedTuplestoreScan(), ExecInitNestLoop(), ExecInitProjectSet(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSampleScan(), ExecInitSeqScan(), ExecInitSetOp(), ExecInitSort(), ExecInitSubPlan(), ExecInitSubqueryScan(), ExecInitTableFuncScan(), ExecInitTidRangeScan(), ExecInitTidScan(), ExecInitUnique(), ExecInitValuesScan(), ExecInitWindowAgg(), ExecInitWorkTableScan(), PlanState::ExecProcNode, ExecSetExecProcNode(), PlanState::initPlan, Plan::initPlan, InstrAlloc(), PlanState::instrument, IsA, lappend(), lfirst, NIL, and nodeTag.

Referenced by EvalPlanQualStart(), ExecInitAgg(), ExecInitAppend(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapOr(), ExecInitForeignScan(), ExecInitGather(), ExecInitGatherMerge(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIncrementalSort(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMemoize(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitProjectSet(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSetOp(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitUnique(), ExecInitWindowAgg(), and InitPlan().

◆ ExecInitNullTupleSlot()

TupleTableSlot* ExecInitNullTupleSlot ( EState estate,
TupleDesc  tupType,
const TupleTableSlotOps tts_ops 
)

Definition at line 1846 of file execTuples.c.

1848 {
1849  TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_ops);
1850 
1851  return ExecStoreAllNullTuple(slot);
1852 }
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
Definition: execTuples.c:1575

References ExecInitExtraTupleSlot(), and ExecStoreAllNullTuple().

Referenced by ExecInitHashJoin(), ExecInitMergeJoin(), and ExecInitNestLoop().

◆ ExecInitQual()

ExprState* ExecInitQual ( List qual,
PlanState parent 
)

Definition at line 213 of file execExpr.c.

214 {
215  ExprState *state;
216  ExprEvalStep scratch = {0};
217  List *adjust_jumps = NIL;
218 
219  /* short-circuit (here and in ExecQual) for empty restriction list */
220  if (qual == NIL)
221  return NULL;
222 
223  Assert(IsA(qual, List));
224 
226  state->expr = (Expr *) qual;
227  state->parent = parent;
228  state->ext_params = NULL;
229 
230  /* mark expression as to be used with ExecQual() */
231  state->flags = EEO_FLAG_IS_QUAL;
232 
233  /* Insert setup steps as needed */
235 
236  /*
237  * ExecQual() needs to return false for an expression returning NULL. That
238  * allows us to short-circuit the evaluation the first time a NULL is
239  * encountered. As qual evaluation is a hot-path this warrants using a
240  * special opcode for qual evaluation that's simpler than BOOL_AND (which
241  * has more complex NULL handling).
242  */
243  scratch.opcode = EEOP_QUAL;
244 
245  /*
246  * We can use ExprState's resvalue/resnull as target for each qual expr.
247  */
248  scratch.resvalue = &state->resvalue;
249  scratch.resnull = &state->resnull;
250 
251  foreach_ptr(Expr, node, qual)
252  {
253  /* first evaluate expression */
254  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
255 
256  /* then emit EEOP_QUAL to detect if it's false (or null) */
257  scratch.d.qualexpr.jumpdone = -1;
258  ExprEvalPushStep(state, &scratch);
259  adjust_jumps = lappend_int(adjust_jumps,
260  state->steps_len - 1);
261  }
262 
263  /* adjust jump targets */
264  foreach_int(jump, adjust_jumps)
265  {
266  ExprEvalStep *as = &state->steps[jump];
267 
268  Assert(as->opcode == EEOP_QUAL);
269  Assert(as->d.qualexpr.jumpdone == -1);
270  as->d.qualexpr.jumpdone = state->steps_len;
271  }
272 
273  /*
274  * At the end, we don't need to do anything more. The last qual expr must
275  * have yielded TRUE, and since its result is stored in the desired output
276  * location, we're done.
277  */
278  scratch.opcode = EEOP_DONE;
279  ExprEvalPushStep(state, &scratch);
280 
282 
283  return state;
284 }
#define foreach_ptr(type, var, lst)
Definition: pg_list.h:469
#define foreach_int(var, lst)
Definition: pg_list.h:470

References Assert(), ExprEvalStep::d, EEO_FLAG_IS_QUAL, EEOP_DONE, EEOP_QUAL, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), foreach_int, foreach_ptr, IsA, lappend_int(), makeNode, NIL, ExprEvalStep::opcode, ExprEvalStep::qualexpr, ExprEvalStep::resnull, and ExprEvalStep::resvalue.

Referenced by CopyFrom(), ExecInitAgg(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitCustomScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitMerge(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNamedTuplestoreScan(), ExecInitNestLoop(), ExecInitPartitionInfo(), ExecInitResult(), ExecInitSampleScan(), ExecInitSeqScan(), ExecInitSubqueryScan(), ExecInitTableFuncScan(), ExecInitTidRangeScan(), ExecInitTidScan(), ExecInitValuesScan(), ExecInitWindowAgg(), ExecInitWorkTableScan(), and ExecPrepareQual().

◆ ExecInitRangeTable()

void ExecInitRangeTable ( EState estate,
List rangeTable,
List permInfos 
)

Definition at line 728 of file execUtils.c.

729 {
730  /* Remember the range table List as-is */
731  estate->es_range_table = rangeTable;
732 
733  /* ... and the RTEPermissionInfo List too */
734  estate->es_rteperminfos = permInfos;
735 
736  /* Set size of associated arrays */
737  estate->es_range_table_size = list_length(rangeTable);
738 
739  /*
740  * Allocate an array to store an open Relation corresponding to each
741  * rangetable entry, and initialize entries to NULL. Relations are opened
742  * and stored here as needed.
743  */
744  estate->es_relations = (Relation *)
745  palloc0(estate->es_range_table_size * sizeof(Relation));
746 
747  /*
748  * es_result_relations and es_rowmarks are also parallel to
749  * es_range_table, but are allocated only if needed.
750  */
751  estate->es_result_relations = NULL;
752  estate->es_rowmarks = NULL;
753 }

References EState::es_range_table, EState::es_range_table_size, EState::es_relations, EState::es_result_relations, EState::es_rowmarks, EState::es_rteperminfos, list_length(), and palloc0().

Referenced by CopyFrom(), create_edata_for_relation(), create_estate_for_relation(), and InitPlan().

◆ ExecInitResultRelation()

void ExecInitResultRelation ( EState estate,
ResultRelInfo resultRelInfo,
Index  rti 
)

Definition at line 814 of file execUtils.c.

816 {
817  Relation resultRelationDesc;
818 
819  resultRelationDesc = ExecGetRangeTableRelation(estate, rti);
820  InitResultRelInfo(resultRelInfo,
821  resultRelationDesc,
822  rti,
823  NULL,
824  estate->es_instrument);
825 
826  if (estate->es_result_relations == NULL)
827  estate->es_result_relations = (ResultRelInfo **)
828  palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
829  estate->es_result_relations[rti - 1] = resultRelInfo;
830 
831  /*
832  * Saving in the list allows to avoid needlessly traversing the whole
833  * array when only a few of its entries are possibly non-NULL.
834  */
836  lappend(estate->es_opened_result_relations, resultRelInfo);
837 }
Relation ExecGetRangeTableRelation(EState *estate, Index rti)
Definition: execUtils.c:762

References EState::es_instrument, EState::es_opened_result_relations, EState::es_range_table_size, EState::es_result_relations, ExecGetRangeTableRelation(), InitResultRelInfo(), lappend(), and palloc0().

Referenced by CopyFrom(), and ExecInitModifyTable().

◆ ExecInitResultSlot()

void ExecInitResultSlot ( PlanState planstate,
const TupleTableSlotOps tts_ops 
)

Definition at line 1778 of file execTuples.c.

1779 {
1780  TupleTableSlot *slot;
1781 
1782  slot = ExecAllocTableSlot(&planstate->state->es_tupleTable,
1783  planstate->ps_ResultTupleDesc, tts_ops);
1784  planstate->ps_ResultTupleSlot = slot;
1785 
1786  planstate->resultopsfixed = planstate->ps_ResultTupleDesc != NULL;
1787  planstate->resultops = tts_ops;
1788  planstate->resultopsset = true;
1789 }
EState * state
Definition: execnodes.h:1045

References EState::es_tupleTable, ExecAllocTableSlot(), PlanState::ps_ResultTupleDesc, PlanState::ps_ResultTupleSlot, PlanState::resultops, PlanState::resultopsfixed, PlanState::resultopsset, and PlanState::state.

Referenced by ExecConditionalAssignProjectionInfo(), and ExecInitResultTupleSlotTL().

◆ ExecInitResultTupleSlotTL()

◆ ExecInitResultTypeTL()

◆ ExecInitScanTupleSlot()

◆ ExecInitTableFunctionResult()

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

Definition at line 56 of file execSRF.c.

58 {
60 
61  state->funcReturnsSet = false;
62  state->expr = expr;
63  state->func.fn_oid = InvalidOid;
64 
65  /*
66  * Normally the passed expression tree will be a FuncExpr, since the
67  * grammar only allows a function call at the top level of a table
68  * function reference. However, if the function doesn't return set then
69  * the planner might have replaced the function call via constant-folding
70  * or inlining. So if we see any other kind of expression node, execute
71  * it via the general ExecEvalExpr() code. That code path will not
72  * support set-returning functions buried in the expression, though.
73  */
74  if (IsA(expr, FuncExpr))
75  {
76  FuncExpr *func = (FuncExpr *) expr;
77 
78  state->funcReturnsSet = func->funcretset;
79  state->args = ExecInitExprList(func->args, parent);
80 
81  init_sexpr(func->funcid, func->inputcollid, expr, state, parent,
82  econtext->ecxt_per_query_memory, func->funcretset, false);
83  }
84  else
85  {
86  state->elidedFuncState = ExecInitExpr(expr, parent);
87  }
88 
89  return state;
90 }

References FuncExpr::args, ExprContext::ecxt_per_query_memory, ExecInitExpr(), ExecInitExprList(), FuncExpr::funcid, init_sexpr(), InvalidOid, IsA, and makeNode.

Referenced by ExecInitFunctionScan().

◆ ExecInsertIndexTuples()

List* ExecInsertIndexTuples ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate,
bool  update,
bool  noDupErr,
bool specConflict,
List arbiterIndexes,
bool  onlySummarizing 
)

Definition at line 298 of file execIndexing.c.

306 {
307  ItemPointer tupleid = &slot->tts_tid;
308  List *result = NIL;
309  int i;
310  int numIndices;
311  RelationPtr relationDescs;
312  Relation heapRelation;
313  IndexInfo **indexInfoArray;
314  ExprContext *econtext;
316  bool isnull[INDEX_MAX_KEYS];
317 
318  Assert(ItemPointerIsValid(tupleid));
319 
320  /*
321  * Get information from the result relation info structure.
322  */
323  numIndices = resultRelInfo->ri_NumIndices;
324  relationDescs = resultRelInfo->ri_IndexRelationDescs;
325  indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
326  heapRelation = resultRelInfo->ri_RelationDesc;
327 
328  /* Sanity check: slot must belong to the same rel as the resultRelInfo. */
329  Assert(slot->tts_tableOid == RelationGetRelid(heapRelation));
330 
331  /*
332  * We will use the EState's per-tuple context for evaluating predicates
333  * and index expressions (creating it if it's not already there).
334  */
335  econtext = GetPerTupleExprContext(estate);
336 
337  /* Arrange for econtext's scan tuple to be the tuple under test */
338  econtext->ecxt_scantuple = slot;
339 
340  /*
341  * for each index, form and insert the index tuple
342  */
343  for (i = 0; i < numIndices; i++)
344  {
345  Relation indexRelation = relationDescs[i];
346  IndexInfo *indexInfo;
347  bool applyNoDupErr;
348  IndexUniqueCheck checkUnique;
349  bool indexUnchanged;
350  bool satisfiesConstraint;
351 
352  if (indexRelation == NULL)
353  continue;
354 
355  indexInfo = indexInfoArray[i];
356 
357  /* If the index is marked as read-only, ignore it */
358  if (!indexInfo->ii_ReadyForInserts)
359  continue;
360 
361  /*
362  * Skip processing of non-summarizing indexes if we only update
363  * summarizing indexes
364  */
365  if (onlySummarizing && !indexInfo->ii_Summarizing)
366  continue;
367 
368  /* Check for partial index */
369  if (indexInfo->ii_Predicate != NIL)
370  {
371  ExprState *predicate;
372 
373  /*
374  * If predicate state not set up yet, create it (in the estate's
375  * per-query context)
376  */
377  predicate = indexInfo->ii_PredicateState;
378  if (predicate == NULL)
379  {
380  predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
381  indexInfo->ii_PredicateState = predicate;
382  }
383 
384  /* Skip this index-update if the predicate isn't satisfied */
385  if (!ExecQual(predicate, econtext))
386  continue;
387  }
388 
389  /*
390  * FormIndexDatum fills in its values and isnull parameters with the
391  * appropriate values for the column(s) of the index.
392  */
393  FormIndexDatum(indexInfo,
394  slot,
395  estate,
396  values,
397  isnull);
398 
399  /* Check whether to apply noDupErr to this index */
400  applyNoDupErr = noDupErr &&
401  (arbiterIndexes == NIL ||
402  list_member_oid(arbiterIndexes,
403  indexRelation->rd_index->indexrelid));
404 
405  /*
406  * The index AM does the actual insertion, plus uniqueness checking.
407  *
408  * For an immediate-mode unique index, we just tell the index AM to
409  * throw error if not unique.
410  *
411  * For a deferrable unique index, we tell the index AM to just detect
412  * possible non-uniqueness, and we add the index OID to the result
413  * list if further checking is needed.
414  *
415  * For a speculative insertion (used by INSERT ... ON CONFLICT), do
416  * the same as for a deferrable unique index.
417  */
418  if (!indexRelation->rd_index->indisunique)
419  checkUnique = UNIQUE_CHECK_NO;
420  else if (applyNoDupErr)
421  checkUnique = UNIQUE_CHECK_PARTIAL;
422  else if (indexRelation->rd_index->indimmediate)
423  checkUnique = UNIQUE_CHECK_YES;
424  else
425  checkUnique = UNIQUE_CHECK_PARTIAL;
426 
427  /*
428  * There's definitely going to be an index_insert() call for this
429  * index. If we're being called as part of an UPDATE statement,
430  * consider if the 'indexUnchanged' = true hint should be passed.
431  */
432  indexUnchanged = update && index_unchanged_by_update(resultRelInfo,
433  estate,
434  indexInfo,
435  indexRelation);
436 
437  satisfiesConstraint =
438  index_insert(indexRelation, /* index relation */
439  values, /* array of index Datums */
440  isnull, /* null flags */
441  tupleid, /* tid of heap tuple */
442  heapRelation, /* heap relation */
443  checkUnique, /* type of uniqueness check to do */
444  indexUnchanged, /* UPDATE without logical change? */
445  indexInfo); /* index AM may need this */
446 
447  /*
448  * If the index has an associated exclusion constraint, check that.
449  * This is simpler than the process for uniqueness checks since we
450  * always insert first and then check. If the constraint is deferred,
451  * we check now anyway, but don't throw error on violation or wait for
452  * a conclusive outcome from a concurrent insertion; instead we'll
453  * queue a recheck event. Similarly, noDupErr callers (speculative
454  * inserters) will recheck later, and wait for a conclusive outcome
455  * then.
456  *
457  * An index for an exclusion constraint can't also be UNIQUE (not an
458  * essential property, we just don't allow it in the grammar), so no
459  * need to preserve the prior state of satisfiesConstraint.
460  */
461  if (indexInfo->ii_ExclusionOps != NULL)
462  {
463  bool violationOK;
464  CEOUC_WAIT_MODE waitMode;
465 
466  if (applyNoDupErr)
467  {
468  violationOK = true;
470  }
471  else if (!indexRelation->rd_index->indimmediate)
472  {
473  violationOK = true;
474  waitMode = CEOUC_NOWAIT;
475  }
476  else
477  {
478  violationOK = false;
479  waitMode = CEOUC_WAIT;
480  }
481 
482  satisfiesConstraint =
484  indexRelation, indexInfo,
485  tupleid, values, isnull,
486  estate, false,
487  waitMode, violationOK, NULL);
488  }
489 
490  if ((checkUnique == UNIQUE_CHECK_PARTIAL ||
491  indexInfo->ii_ExclusionOps != NULL) &&
492  !satisfiesConstraint)
493  {
494  /*
495  * The tuple potentially violates the uniqueness or exclusion
496  * constraint, so make a note of the index so that we can re-check
497  * it later. Speculative inserters are told if there was a
498  * speculative conflict, since that always requires a restart.
499  */
500  result = lappend_oid(result, RelationGetRelid(indexRelation));
501  if (indexRelation->rd_index->indimmediate && specConflict)
502  *specConflict = true;
503  }
504  }
505 
506  return result;
507 }
static bool index_unchanged_by_update(ResultRelInfo *resultRelInfo, EState *estate, IndexInfo *indexInfo, Relation indexRelation)
Definition: execIndexing.c:963
CEOUC_WAIT_MODE
Definition: execIndexing.c:121
@ CEOUC_NOWAIT
Definition: execIndexing.c:123
@ CEOUC_LIVELOCK_PREVENTING_WAIT
Definition: execIndexing.c:124
IndexUniqueCheck
Definition: genam.h:116
@ UNIQUE_CHECK_NO
Definition: genam.h:117
@ UNIQUE_CHECK_PARTIAL
Definition: genam.h:119
@ UNIQUE_CHECK_YES
Definition: genam.h:118
bool index_insert(Relation indexRelation, Datum *values, bool *isnull, ItemPointer heap_t_ctid, Relation heapRelation, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
Definition: indexam.c:213
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
bool ii_Summarizing
Definition: execnodes.h:204
Oid tts_tableOid
Definition: tuptable.h:130
ItemPointerData tts_tid
Definition: tuptable.h:129

References Assert(), CEOUC_LIVELOCK_PREVENTING_WAIT, CEOUC_NOWAIT, CEOUC_WAIT, check_exclusion_or_unique_constraint(), ExprContext::ecxt_scantuple, ExecPrepareQual(), ExecQual(), FormIndexDatum(), GetPerTupleExprContext, i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, IndexInfo::ii_ReadyForInserts, IndexInfo::ii_Summarizing, index_insert(), INDEX_MAX_KEYS, index_unchanged_by_update(), ItemPointerIsValid(), lappend_oid(), list_member_oid(), NIL, RelationData::rd_index, RelationGetRelid, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, TupleTableSlot::tts_tableOid, TupleTableSlot::tts_tid, UNIQUE_CHECK_NO, UNIQUE_CHECK_PARTIAL, UNIQUE_CHECK_YES, and values.

Referenced by CopyFrom(), CopyMultiInsertBufferFlush(), ExecInsert(), ExecSimpleRelationInsert(), ExecSimpleRelationUpdate(), and ExecUpdateEpilogue().

◆ ExecLookupResultRelByOid()

ResultRelInfo* ExecLookupResultRelByOid ( ModifyTableState node,
Oid  resultoid,
bool  missing_ok,
bool  update_cache 
)

Definition at line 4062 of file nodeModifyTable.c.

4064 {
4065  if (node->mt_resultOidHash)
4066  {
4067  /* Use the pre-built hash table to locate the rel */
4068  MTTargetRelLookup *mtlookup;
4069 
4070  mtlookup = (MTTargetRelLookup *)
4071  hash_search(node->mt_resultOidHash, &resultoid, HASH_FIND, NULL);
4072  if (mtlookup)
4073  {
4074  if (update_cache)
4075  {
4076  node->mt_lastResultOid = resultoid;
4077  node->mt_lastResultIndex = mtlookup->relationIndex;
4078  }
4079  return node->resultRelInfo + mtlookup->relationIndex;
4080  }
4081  }
4082  else
4083  {
4084  /* With few target rels, just search the ResultRelInfo array */
4085  for (int ndx = 0; ndx < node->mt_nrels; ndx++)
4086  {
4087  ResultRelInfo *rInfo = node->resultRelInfo + ndx;
4088 
4089  if (RelationGetRelid(rInfo->ri_RelationDesc) == resultoid)
4090  {
4091  if (update_cache)
4092  {
4093  node->mt_lastResultOid = resultoid;
4094  node->mt_lastResultIndex = ndx;
4095  }
4096  return rInfo;
4097  }
4098  }
4099  }
4100 
4101  if (!missing_ok)
4102  elog(ERROR, "incorrect result relation OID %u", resultoid);
4103  return NULL;
4104 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
@ HASH_FIND
Definition: hsearch.h:113
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1286
HTAB * mt_resultOidHash
Definition: execnodes.h:1308

References elog, ERROR, HASH_FIND, hash_search(), ModifyTableState::mt_lastResultIndex, ModifyTableState::mt_lastResultOid, ModifyTableState::mt_nrels, ModifyTableState::mt_resultOidHash, RelationGetRelid, MTTargetRelLookup::relationIndex, ModifyTableState::resultRelInfo, and ResultRelInfo::ri_RelationDesc.

Referenced by ExecFindPartition(), and ExecModifyTable().

◆ ExecMakeFunctionResultSet()

Datum ExecMakeFunctionResultSet ( SetExprState fcache,
ExprContext econtext,
MemoryContext  argContext,
bool isNull,
ExprDoneCond isDone 
)

Definition at line 497 of file execSRF.c.

502 {
503  List *arguments;
504  Datum result;
505  FunctionCallInfo fcinfo;
506  PgStat_FunctionCallUsage fcusage;
507  ReturnSetInfo rsinfo;
508  bool callit;
509  int i;
510 
511 restart:
512 
513  /* Guard against stack overflow due to overly complex expressions */
515 
516  /*
517  * If a previous call of the function returned a set result in the form of
518  * a tuplestore, continue reading rows from the tuplestore until it's
519  * empty.
520  */
521  if (fcache->funcResultStore)
522  {
523  TupleTableSlot *slot = fcache->funcResultSlot;
524  MemoryContext oldContext;
525  bool foundTup;
526 
527  /*
528  * Have to make sure tuple in slot lives long enough, otherwise
529  * clearing the slot could end up trying to free something already
530  * freed.
531  */
532  oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
533  foundTup = tuplestore_gettupleslot(fcache->funcResultStore, true, false,
534  fcache->funcResultSlot);
535  MemoryContextSwitchTo(oldContext);
536 
537  if (foundTup)
538  {
539  *isDone = ExprMultipleResult;
540  if (fcache->funcReturnsTuple)
541  {
542  /* We must return the whole tuple as a Datum. */
543  *isNull = false;
545  }
546  else
547  {
548  /* Extract the first column and return it as a scalar. */
549  return slot_getattr(fcache->funcResultSlot, 1, isNull);
550  }
551  }
552  /* Exhausted the tuplestore, so clean up */
554  fcache->funcResultStore = NULL;
555  *isDone = ExprEndResult;
556  *isNull = true;
557  return (Datum) 0;
558  }
559 
560  /*
561  * arguments is a list of expressions to evaluate before passing to the
562  * function manager. We skip the evaluation if it was already done in the
563  * previous call (ie, we are continuing the evaluation of a set-valued
564  * function). Otherwise, collect the current argument values into fcinfo.
565  *
566  * The arguments have to live in a context that lives at least until all
567  * rows from this SRF have been returned, otherwise ValuePerCall SRFs
568  * would reference freed memory after the first returned row.
569  */
570  fcinfo = fcache->fcinfo;
571  arguments = fcache->args;
572  if (!fcache->setArgsValid)
573  {
574  MemoryContext oldContext = MemoryContextSwitchTo(argContext);
575 
576  ExecEvalFuncArgs(fcinfo, arguments, econtext);
577  MemoryContextSwitchTo(oldContext);
578  }
579  else
580  {
581  /* Reset flag (we may set it again below) */
582  fcache->setArgsValid = false;
583  }
584 
585  /*
586  * Now call the function, passing the evaluated parameter values.
587  */
588 
589  /* Prepare a resultinfo node for communication. */
590  fcinfo->resultinfo = (Node *) &rsinfo;
591  rsinfo.type = T_ReturnSetInfo;
592  rsinfo.econtext = econtext;
593  rsinfo.expectedDesc = fcache->funcResultDesc;
595  /* note we do not set SFRM_Materialize_Random or _Preferred */
596  rsinfo.returnMode = SFRM_ValuePerCall;
597  /* isDone is filled below */
598  rsinfo.setResult = NULL;
599  rsinfo.setDesc = NULL;
600 
601  /*
602  * If function is strict, and there are any NULL arguments, skip calling
603  * the function.
604  */
605  callit = true;
606  if (fcache->func.fn_strict)
607  {
608  for (i = 0; i < fcinfo->nargs; i++)
609  {
610  if (fcinfo->args[i].isnull)
611  {
612  callit = false;
613  break;
614  }
615  }
616  }
617 
618  if (callit)
619  {
620  pgstat_init_function_usage(fcinfo, &fcusage);
621 
622  fcinfo->isnull = false;
623  rsinfo.isDone = ExprSingleResult;
624  result = FunctionCallInvoke(fcinfo);
625  *isNull = fcinfo->isnull;
626  *isDone = rsinfo.isDone;
627 
628  pgstat_end_function_usage(&fcusage,
629  rsinfo.isDone != ExprMultipleResult);
630  }
631  else
632  {
633  /* for a strict SRF, result for NULL is an empty set */
634  result = (Datum) 0;
635  *isNull = true;
636  *isDone = ExprEndResult;
637  }
638 
639  /* Which protocol does function want to use? */
640  if (rsinfo.returnMode == SFRM_ValuePerCall)
641  {
642  if (*isDone != ExprEndResult)
643  {
644  /*
645  * Save the current argument values to re-use on the next call.
646  */
647  if (*isDone == ExprMultipleResult)
648  {
649  fcache->setArgsValid = true;
650  /* Register cleanup callback if we didn't already */
651  if (!fcache->shutdown_reg)
652  {
655  PointerGetDatum(fcache));
656  fcache->shutdown_reg = true;
657  }
658  }
659  }
660  }
661  else if (rsinfo.returnMode == SFRM_Materialize)
662  {
663  /* check we're on the same page as the function author */
664  if (rsinfo.isDone != ExprSingleResult)
665  ereport(ERROR,
666  (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
667  errmsg("table-function protocol for materialize mode was not followed")));
668  if (rsinfo.setResult != NULL)
669  {
670  /* prepare to return values from the tuplestore */
671  ExecPrepareTuplestoreResult(fcache, econtext,
672  rsinfo.setResult,
673  rsinfo.setDesc);
674  /* loop back to top to start returning from tuplestore */
675  goto restart;
676  }
677  /* if setResult was left null, treat it as empty set */
678  *isDone = ExprEndResult;
679  *isNull = true;
680  result = (Datum) 0;
681  }
682  else
683  ereport(ERROR,
684  (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
685  errmsg("unrecognized table-function returnMode: %d",
686  (int) rsinfo.returnMode)));
687 
688  return result;
689 }
static void ExecEvalFuncArgs(FunctionCallInfo fcinfo, List *argList, ExprContext *econtext)
Definition: execSRF.c:834
static void ShutdownSetExpr(Datum arg)
Definition: execSRF.c:810
static void ExecPrepareTuplestoreResult(SetExprState *sexpr, ExprContext *econtext, Tuplestorestate *resultStore, TupleDesc resultDesc)
Definition: execSRF.c:864
Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
Definition: execTuples.c:1722
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
Definition: execUtils.c:897
@ ExprSingleResult
Definition: execnodes.h:303
@ ExprMultipleResult
Definition: execnodes.h:304
@ ExprEndResult
Definition: execnodes.h:305
@ SFRM_ValuePerCall
Definition: execnodes.h:316
@ SFRM_Materialize
Definition: execnodes.h:317
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
bool fn_strict
Definition: fmgr.h:61
fmNodePtr resultinfo
Definition: fmgr.h:89
NodeTag type
Definition: execnodes.h:330
SetFunctionReturnMode returnMode
Definition: execnodes.h:336
ExprContext * econtext
Definition: execnodes.h:332
TupleDesc setDesc
Definition: execnodes.h:340
Tuplestorestate * setResult
Definition: execnodes.h:339
TupleDesc expectedDesc
Definition: execnodes.h:333
int allowedModes
Definition: execnodes.h:334
ExprDoneCond isDone
Definition: execnodes.h:337
FunctionCallInfo fcinfo
Definition: execnodes.h:948
TupleTableSlot * funcResultSlot
Definition: execnodes.h:911
Tuplestorestate * funcResultStore
Definition: execnodes.h:910
bool shutdown_reg
Definition: execnodes.h:941
bool funcReturnsTuple
Definition: execnodes.h:918
TupleDesc funcResultDesc
Definition: execnodes.h:917
FmgrInfo func
Definition: execnodes.h:903
List * args
Definition: execnodes.h:889
bool setArgsValid
Definition: execnodes.h:933
MemoryContext tts_mcxt
Definition: tuptable.h:128
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1078
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453

References ReturnSetInfo::allowedModes, FunctionCallInfoBaseData::args, SetExprState::args, check_stack_depth(), ReturnSetInfo::econtext, ereport, errcode(), errmsg(), ERROR, ExecEvalFuncArgs(), ExecFetchSlotHeapTupleDatum(), ExecPrepareTuplestoreResult(), ReturnSetInfo::expectedDesc, ExprEndResult, ExprMultipleResult, ExprSingleResult, SetExprState::fcinfo, FmgrInfo::fn_strict, SetExprState::func, SetExprState::funcResultDesc, SetExprState::funcResultSlot, SetExprState::funcResultStore, SetExprState::funcReturnsTuple, FunctionCallInvoke, i, ReturnSetInfo::isDone, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, MemoryContextSwitchTo(), FunctionCallInfoBaseData::nargs, pgstat_end_function_usage(), pgstat_init_function_usage(), PointerGetDatum(), RegisterExprContextCallback(), FunctionCallInfoBaseData::resultinfo, ReturnSetInfo::returnMode, SetExprState::setArgsValid, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_ValuePerCall, SetExprState::shutdown_reg, ShutdownSetExpr(), slot_getattr(), TupleTableSlot::tts_mcxt, tuplestore_end(), tuplestore_gettupleslot(), and ReturnSetInfo::type.

Referenced by ExecProjectSRF().

◆ ExecMakeTableFunctionResult()

Tuplestorestate* ExecMakeTableFunctionResult ( SetExprState setexpr,
ExprContext econtext,
MemoryContext  argContext,
TupleDesc  expectedDesc,
bool  randomAccess 
)

Definition at line 101 of file execSRF.c.

106 {
107  Tuplestorestate *tupstore = NULL;
108  TupleDesc tupdesc = NULL;
109  Oid funcrettype;
110  bool returnsTuple;
111  bool returnsSet = false;
112  FunctionCallInfo fcinfo;
113  PgStat_FunctionCallUsage fcusage;
114  ReturnSetInfo rsinfo;
115  HeapTupleData tmptup;
116  MemoryContext callerContext;
117  bool first_time = true;
118 
119  /*
120  * Execute per-tablefunc actions in appropriate context.
121  *
122  * The FunctionCallInfo needs to live across all the calls to a
123  * ValuePerCall function, so it can't be allocated in the per-tuple
124  * context. Similarly, the function arguments need to be evaluated in a
125  * context that is longer lived than the per-tuple context: The argument
126  * values would otherwise disappear when we reset that context in the
127  * inner loop. As the caller's CurrentMemoryContext is typically a
128  * query-lifespan context, we don't want to leak memory there. We require
129  * the caller to pass a separate memory context that can be used for this,
130  * and can be reset each time through to avoid bloat.
131  */
132  MemoryContextReset(argContext);
133  callerContext = MemoryContextSwitchTo(argContext);
134 
135  funcrettype = exprType((Node *) setexpr->expr);
136 
137  returnsTuple = type_is_rowtype(funcrettype);
138 
139  /*
140  * Prepare a resultinfo node for communication. We always do this even if
141  * not expecting a set result, so that we can pass expectedDesc. In the
142  * generic-expression case, the expression doesn't actually get to see the
143  * resultinfo, but set it up anyway because we use some of the fields as
144  * our own state variables.
145  */
146  rsinfo.type = T_ReturnSetInfo;
147  rsinfo.econtext = econtext;
148  rsinfo.expectedDesc = expectedDesc;
150  if (randomAccess)
151  rsinfo.allowedModes |= (int) SFRM_Materialize_Random;
152  rsinfo.returnMode = SFRM_ValuePerCall;
153  /* isDone is filled below */
154  rsinfo.setResult = NULL;
155  rsinfo.setDesc = NULL;
156 
157  fcinfo = palloc(SizeForFunctionCallInfo(list_length(setexpr->args)));
158 
159  /*
160  * Normally the passed expression tree will be a SetExprState, since the
161  * grammar only allows a function call at the top level of a table
162  * function reference. However, if the function doesn't return set then
163  * the planner might have replaced the function call via constant-folding
164  * or inlining. So if we see any other kind of expression node, execute
165  * it via the general ExecEvalExpr() code; the only difference is that we
166  * don't get a chance to pass a special ReturnSetInfo to any functions
167  * buried in the expression.
168  */
169  if (!setexpr->elidedFuncState)
170  {
171  /*
172  * This path is similar to ExecMakeFunctionResultSet.
173  */
174  returnsSet = setexpr->funcReturnsSet;
175  InitFunctionCallInfoData(*fcinfo, &(setexpr->func),
176  list_length(setexpr->args),
177  setexpr->fcinfo->fncollation,
178  NULL, (Node *) &rsinfo);
179  /* evaluate the function's argument list */
180  Assert(CurrentMemoryContext == argContext);
181  ExecEvalFuncArgs(fcinfo, setexpr->args, econtext);
182 
183  /*
184  * If function is strict, and there are any NULL arguments, skip
185  * calling the function and act like it returned NULL (or an empty
186  * set, in the returns-set case).
187  */
188  if (setexpr->func.fn_strict)
189  {
190  int i;
191 
192  for (i = 0; i < fcinfo->nargs; i++)
193  {
194  if (fcinfo->args[i].isnull)
195  goto no_function_result;
196  }
197  }
198  }
199  else
200  {
201  /* Treat setexpr as a generic expression */
202  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
203  }
204 
205  /*
206  * Switch to short-lived context for calling the function or expression.
207  */
209 
210  /*
211  * Loop to handle the ValuePerCall protocol (which is also the same
212  * behavior needed in the generic ExecEvalExpr path).
213  */
214  for (;;)
215  {
216  Datum result;
217 
219 
220  /*
221  * Reset per-tuple memory context before each call of the function or
222  * expression. This cleans up any local memory the function may leak
223  * when called.
224  */
225  ResetExprContext(econtext);
226 
227  /* Call the function or expression one time */
228  if (!setexpr->elidedFuncState)
229  {
230  pgstat_init_function_usage(fcinfo, &fcusage);
231 
232  fcinfo->isnull = false;
233  rsinfo.isDone = ExprSingleResult;
234  result = FunctionCallInvoke(fcinfo);
235 
236  pgstat_end_function_usage(&fcusage,
237  rsinfo.isDone != ExprMultipleResult);
238  }
239  else
240  {
241  result =
242  ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo->isnull);
243  rsinfo.isDone = ExprSingleResult;
244  }
245 
246  /* Which protocol does function want to use? */
247  if (rsinfo.returnMode == SFRM_ValuePerCall)
248  {
249  /*
250  * Check for end of result set.
251  */
252  if (rsinfo.isDone == ExprEndResult)
253  break;
254 
255  /*
256  * If first time through, build tuplestore for result. For a
257  * scalar function result type, also make a suitable tupdesc.
258  */
259  if (first_time)
260  {
261  MemoryContext oldcontext =
263 
264  tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
265  rsinfo.setResult = tupstore;
266  if (!returnsTuple)
267  {
268  tupdesc = CreateTemplateTupleDesc(1);
269  TupleDescInitEntry(tupdesc,
270  (AttrNumber) 1,
271  "column",
272  funcrettype,
273  -1,
274  0);
275  rsinfo.setDesc = tupdesc;
276  }
277  MemoryContextSwitchTo(oldcontext);
278  }
279 
280  /*
281  * Store current resultset item.
282  */
283  if (returnsTuple)
284  {
285  if (!fcinfo->isnull)
286  {
288 
289  if (tupdesc == NULL)
290  {
291  MemoryContext oldcontext =
293 
294  /*
295  * This is the first non-NULL result from the
296  * function. Use the type info embedded in the
297  * rowtype Datum to look up the needed tupdesc. Make
298  * a copy for the query.
299  */
302  rsinfo.setDesc = tupdesc;
303  MemoryContextSwitchTo(oldcontext);
304  }
305  else
306  {
307  /*
308  * Verify all later returned rows have same subtype;
309  * necessary in case the type is RECORD.
310  */
311  if (HeapTupleHeaderGetTypeId(td) != tupdesc->tdtypeid ||
312  HeapTupleHeaderGetTypMod(td) != tupdesc->tdtypmod)
313  ereport(ERROR,
314  (errcode(ERRCODE_DATATYPE_MISMATCH),
315  errmsg("rows returned by function are not all of the same row type")));
316  }
317 
318  /*
319  * tuplestore_puttuple needs a HeapTuple not a bare
320  * HeapTupleHeader, but it doesn't need all the fields.
321  */
323  tmptup.t_data = td;
324 
325  tuplestore_puttuple(tupstore, &tmptup);
326  }
327  else
328  {
329  /*
330  * NULL result from a tuple-returning function; expand it
331  * to a row of all nulls. We rely on the expectedDesc to
332  * form such rows. (Note: this would be problematic if
333  * tuplestore_putvalues saved the tdtypeid/tdtypmod from
334  * the provided descriptor, since that might not match
335  * what we get from the function itself. But it doesn't.)
336  */
337  int natts = expectedDesc->natts;
338  bool *nullflags;
339 
340  nullflags = (bool *) palloc(natts * sizeof(bool));
341  memset(nullflags, true, natts * sizeof(bool));
342  tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
343  }
344  }
345  else
346  {
347  /* Scalar-type case: just store the function result */
348  tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo->isnull);
349  }
350 
351  /*
352  * Are we done?
353  */
354  if (rsinfo.isDone != ExprMultipleResult)
355  break;
356 
357  /*
358  * Check that set-returning functions were properly declared.
359  * (Note: for historical reasons, we don't complain if a non-SRF
360  * returns ExprEndResult; that's treated as returning NULL.)
361  */
362  if (!returnsSet)
363  ereport(ERROR,
364  (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
365  errmsg("table-function protocol for value-per-call mode was not followed")));
366  }
367  else if (rsinfo.returnMode == SFRM_Materialize)
368  {
369  /* check we're on the same page as the function author */
370  if (!first_time || rsinfo.isDone != ExprSingleResult || !returnsSet)
371  ereport(ERROR,
372  (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
373  errmsg("table-function protocol for materialize mode was not followed")));
374  /* Done evaluating the set result */
375  break;
376  }
377  else
378  ereport(ERROR,
379  (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
380  errmsg("unrecognized table-function returnMode: %d",
381  (int) rsinfo.returnMode)));
382 
383  first_time = false;
384  }
385 
386 no_function_result:
387 
388  /*
389  * If we got nothing from the function (ie, an empty-set or NULL result),
390  * we have to create the tuplestore to return, and if it's a
391  * non-set-returning function then insert a single all-nulls row. As
392  * above, we depend on the expectedDesc to manufacture the dummy row.
393  */
394  if (rsinfo.setResult == NULL)
395  {
396  MemoryContext oldcontext =
398 
399  tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
400  rsinfo.setResult = tupstore;
401  MemoryContextSwitchTo(oldcontext);
402 
403  if (!returnsSet)
404  {
405  int natts = expectedDesc->natts;
406  bool *nullflags;
407 
408  nullflags = (bool *) palloc(natts * sizeof(bool));
409  memset(nullflags, true, natts * sizeof(bool));
410  tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
411  }
412  }
413 
414  /*
415  * If function provided a tupdesc, cross-check it. We only really need to
416  * do this for functions returning RECORD, but might as well do it always.
417  */
418  if (rsinfo.setDesc)
419  {
420  tupledesc_match(expectedDesc, rsinfo.setDesc);
421 
422  /*
423  * If it is a dynamically-allocated TupleDesc, free it: it is
424  * typically allocated in a per-query context, so we must avoid
425  * leaking it across multiple usages.
426  */
427  if (rsinfo.setDesc->tdrefcount == -1)
428  FreeTupleDesc(rsinfo.setDesc);
429  }
430 
431  MemoryContextSwitchTo(callerContext);
432 
433  /* All done, pass back the tuplestore */
434  return rsinfo.setResult;
435 }
static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
Definition: execSRF.c:943
@ SFRM_Materialize_Preferred
Definition: execnodes.h:319
@ SFRM_Materialize_Random
Definition: execnodes.h:318
#define ResetExprContext(econtext)
Definition: executor.h:544
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:333
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2611
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:371
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Expr * expr
Definition: execnodes.h:888
bool funcReturnsSet
Definition: execnodes.h:924
ExprState * elidedFuncState
Definition: execnodes.h:896
int tdrefcount
Definition: tupdesc.h:84
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:331
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:67
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:651
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:750
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
Definition: typcache.c:1867

References ReturnSetInfo::allowedModes, FunctionCallInfoBaseData::args, SetExprState::args, Assert(), CHECK_FOR_INTERRUPTS, CreateTemplateTupleDesc(), CurrentMemoryContext, DatumGetHeapTupleHeader, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, SetExprState::elidedFuncState, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr(), ExecEvalFuncArgs(), ReturnSetInfo::expectedDesc, SetExprState::expr, ExprEndResult, ExprMultipleResult, ExprSingleResult, exprType(), SetExprState::fcinfo, FmgrInfo::fn_strict, FunctionCallInfoBaseData::fncollation, FreeTupleDesc(), SetExprState::func, SetExprState::funcReturnsSet, FunctionCallInvoke, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, InitFunctionCallInfoData, InvalidOid, ReturnSetInfo::isDone, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, list_length(), lookup_rowtype_tupdesc_copy(), MemoryContextReset(), MemoryContextSwitchTo(), FunctionCallInfoBaseData::nargs, TupleDescData::natts, palloc(), pgstat_end_function_usage(), pgstat_init_function_usage(), ResetExprContext, ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Preferred, SFRM_Materialize_Random, SFRM_ValuePerCall, SizeForFunctionCallInfo, HeapTupleData::t_data, HeapTupleData::t_len, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, tupledesc_match(), TupleDescInitEntry(), tuplestore_begin_heap(), tuplestore_puttuple(), tuplestore_putvalues(), ReturnSetInfo::type, type_is_rowtype(), and work_mem.

Referenced by FunctionNext().

◆ ExecMarkPos()

void ExecMarkPos ( PlanState node)

Definition at line 326 of file execAmi.c.

327 {
328  switch (nodeTag(node))
329  {
330  case T_IndexScanState:
332  break;
333 
334  case T_IndexOnlyScanState:
336  break;
337 
338  case T_CustomScanState:
340  break;
341 
342  case T_MaterialState:
344  break;
345 
346  case T_SortState:
347  ExecSortMarkPos((SortState *) node);
348  break;
349 
350  case T_ResultState:
351  ExecResultMarkPos((ResultState *) node);
352  break;
353 
354  default:
355  /* don't make hard error unless caller asks to restore... */
356  elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
357  break;
358  }
359 }
#define DEBUG2
Definition: elog.h:29
void ExecCustomMarkPos(CustomScanState *node)
Definition: nodeCustom.c:139
void ExecIndexOnlyMarkPos(IndexOnlyScanState *node)
void ExecIndexMarkPos(IndexScanState *node)
void ExecMaterialMarkPos(MaterialState *node)
Definition: nodeMaterial.c:262
void ExecResultMarkPos(ResultState *node)
Definition: nodeResult.c:146
void ExecSortMarkPos(SortState *node)
Definition: nodeSort.c:329

References DEBUG2, elog, ExecCustomMarkPos(), ExecIndexMarkPos(), ExecIndexOnlyMarkPos(), ExecMaterialMarkPos(), ExecResultMarkPos(), ExecSortMarkPos(), and nodeTag.

Referenced by ExecMergeJoin(), and ExecResultMarkPos().

◆ ExecMaterializesOutput()

bool ExecMaterializesOutput ( NodeTag  plantype)

Definition at line 635 of file execAmi.c.

636 {
637  switch (plantype)
638  {
639  case T_Material:
640  case T_FunctionScan:
641  case T_TableFuncScan:
642  case T_CteScan:
643  case T_NamedTuplestoreScan:
644  case T_WorkTableScan:
645  case T_Sort:
646  return true;
647 
648  default:
649  break;
650  }
651 
652  return false;
653 }

Referenced by build_subplan(), cost_subplan(), and match_unsorted_outer().

◆ ExecOpenIndices()

void ExecOpenIndices ( ResultRelInfo resultRelInfo,
bool  speculative 
)

Definition at line 156 of file execIndexing.c.

157 {
158  Relation resultRelation = resultRelInfo->ri_RelationDesc;
159  List *indexoidlist;
160  ListCell *l;
161  int len,
162  i;
163  RelationPtr relationDescs;
164  IndexInfo **indexInfoArray;
165 
166  resultRelInfo->ri_NumIndices = 0;
167 
168  /* fast path if no indexes */
169  if (!RelationGetForm(resultRelation)->relhasindex)
170  return;
171 
172  /*
173  * Get cached list of index OIDs
174  */
175  indexoidlist = RelationGetIndexList(resultRelation);
176  len = list_length(indexoidlist);
177  if (len == 0)
178  return;
179 
180  /*
181  * allocate space for result arrays
182  */
183  relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
184  indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
185 
186  resultRelInfo->ri_NumIndices = len;
187  resultRelInfo->ri_IndexRelationDescs = relationDescs;
188  resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
189 
190  /*
191  * For each index, open the index relation and save pg_index info. We
192  * acquire RowExclusiveLock, signifying we will update the index.
193  *
194  * Note: we do this even if the index is not indisready; it's not worth
195  * the trouble to optimize for the case where it isn't.
196  */
197  i = 0;
198  foreach(l, indexoidlist)
199  {
200  Oid indexOid = lfirst_oid(l);
201  Relation indexDesc;
202  IndexInfo *ii;
203 
204  indexDesc = index_open(indexOid, RowExclusiveLock);
205 
206  /* extract index key information from the index's pg_index info */
207  ii = BuildIndexInfo(indexDesc);
208 
209  /*
210  * If the indexes are to be used for speculative insertion, add extra
211  * information required by unique index entries.
212  */
213  if (speculative && ii->ii_Unique)
214  BuildSpeculativeIndexInfo(indexDesc, ii);
215 
216  relationDescs[i] = indexDesc;
217  indexInfoArray[i] = ii;
218  i++;
219  }
220 
221  list_free(indexoidlist);
222 }
void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
Definition: index.c:2645
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:2407
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
void list_free(List *list)
Definition: list.c:1546
#define RelationGetForm(relation)
Definition: rel.h:499
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4749
Relation * RelationPtr
Definition: relcache.h:35

References BuildIndexInfo(), BuildSpeculativeIndexInfo(), i, IndexInfo::ii_Unique, index_open(), len, lfirst_oid, list_free(), list_length(), palloc(), RelationGetForm, RelationGetIndexList(), ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, and RowExclusiveLock.

Referenced by apply_handle_delete_internal(), apply_handle_insert_internal(), apply_handle_tuple_routing(), apply_handle_update_internal(), CatalogOpenIndexes(), CopyFrom(), ExecInitPartitionInfo(), ExecInsert(), and ExecUpdatePrologue().

◆ ExecOpenScanRelation()

Relation ExecOpenScanRelation ( EState estate,
Index  scanrelid,
int  eflags 
)

Definition at line 697 of file execUtils.c.

698 {
699  Relation rel;
700 
701  /* Open the relation. */
702  rel = ExecGetRangeTableRelation(estate, scanrelid);
703 
704  /*
705  * Complain if we're attempting a scan of an unscannable relation, except
706  * when the query won't actually be run. This is a slightly klugy place
707  * to do this, perhaps, but there is no better place.
708  */
709  if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
710  !RelationIsScannable(rel))
711  ereport(ERROR,
712  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
713  errmsg("materialized view \"%s\" has not been populated",
715  errhint("Use the REFRESH MATERIALIZED VIEW command.")));
716 
717  return rel;
718 }
#define EXEC_FLAG_WITH_NO_DATA
Definition: executor.h:71
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:65
#define RelationIsScannable(relation)
Definition: rel.h:669

References ereport, errcode(), errhint(), errmsg(), ERROR, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_WITH_NO_DATA, ExecGetRangeTableRelation(), RelationGetRelationName, and RelationIsScannable.

Referenced by ExecInitBitmapHeapScan(), ExecInitCustomScan(), ExecInitForeignScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitSampleScan(), ExecInitSeqScan(), ExecInitTidRangeScan(), ExecInitTidScan(), and postgresBeginDirectModify().

◆ ExecPartitionCheck()

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

Definition at line 1790 of file execMain.c.

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

References ExprContext::ecxt_scantuple, EState::es_query_cxt, ExecCheck(), ExecPartitionCheckEmitError(), ExecPrepareCheck(), GetPerTupleExprContext, MemoryContextSwitchTo(), RelationGetPartitionQual(), ResultRelInfo::ri_PartitionCheckExpr, ResultRelInfo::ri_RelationDesc, and success.

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

◆ ExecPartitionCheckEmitError()

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

Definition at line 1843 of file execMain.c.

1846 {
1847  Oid root_relid;
1848  TupleDesc tupdesc;
1849  char *val_desc;
1850  Bitmapset *modifiedCols;
1851 
1852  /*
1853  * If the tuple has been routed, it's been converted to the partition's
1854  * rowtype, which might differ from the root table's. We must convert it
1855  * back to the root table's rowtype so that val_desc in the error message
1856  * matches the input tuple.
1857  */
1858  if (resultRelInfo->ri_RootResultRelInfo)
1859  {
1860  ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1861  TupleDesc old_tupdesc;
1862  AttrMap *map;
1863 
1864  root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
1865  tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1866 
1867  old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1868  /* a reverse map */
1869  map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc, false);
1870 
1871  /*
1872  * Partition-specific slot's tupdesc can't be changed, so allocate a
1873  * new one.
1874  */
1875  if (map != NULL)
1876  slot = execute_attr_map_slot(map, slot,
1877  MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
1878  modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
1879  ExecGetUpdatedCols(rootrel, estate));
1880  }
1881  else
1882  {
1883  root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1884  tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1885  modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1886  ExecGetUpdatedCols(resultRelInfo, estate));
1887  }
1888 
1889  val_desc = ExecBuildSlotValueDescription(root_relid,
1890  slot,
1891  tupdesc,
1892  modifiedCols,
1893  64);
1894  ereport(ERROR,
1895  (errcode(ERRCODE_CHECK_VIOLATION),
1896  errmsg("new row for relation \"%s\" violates partition constraint",
1897  RelationGetRelationName(resultRelInfo->ri_RelationDesc)),
1898  val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1899  errtable(resultRelInfo->ri_RelationDesc)));
1900 }
int errtable(Relation rel)
Definition: relcache.c:5934

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

Referenced by ExecCrossPartitionUpdate(), and ExecPartitionCheck().

◆ ExecPrepareCheck()

ExprState* ExecPrepareCheck ( List qual,
EState estate 
)

Definition at line 783 of file execExpr.c.

784 {
785  ExprState *result;
786  MemoryContext oldcontext;
787 
788  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
789 
790  qual = (List *) expression_planner((Expr *) qual);
791 
792  result = ExecInitCheck(qual, NULL);
793 
794  MemoryContextSwitchTo(oldcontext);
795 
796  return result;
797 }
ExprState * ExecInitCheck(List *qual, PlanState *parent)
Definition: execExpr.c:299
Expr * expression_planner(Expr *expr)
Definition: planner.c:6400

References EState::es_query_cxt, ExecInitCheck(), expression_planner(), and MemoryContextSwitchTo().

Referenced by ExecPartitionCheck().

◆ ExecPrepareExpr()

ExprState* ExecPrepareExpr ( Expr node,
EState estate 
)

Definition at line 732 of file execExpr.c.

733 {
734  ExprState *result;
735  MemoryContext oldcontext;
736 
737  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
738 
739  node = expression_planner(node);
740 
741  result = ExecInitExpr(node, NULL);
742 
743  MemoryContextSwitchTo(oldcontext);
744 
745  return result;
746 }

References EState::es_query_cxt, ExecInitExpr(), expression_planner(), and MemoryContextSwitchTo().

Referenced by ATRewriteTable(), check_default_partition_contents(), compute_expr_stats(), ExecInitStoredGenerated(), ExecPrepareExprList(), ExecRelCheck(), ExecuteCallStmt(), pgoutput_row_filter_init(), StoreAttrDefault(), and validateDomainConstraint().

◆ ExecPrepareExprList()

List* ExecPrepareExprList ( List nodes,
EState estate 
)

Definition at line 806 of file execExpr.c.

807 {
808  List *result = NIL;
809  MemoryContext oldcontext;
810  ListCell *lc;
811 
812  /* Ensure that the list cell nodes are in the right context too */
813  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
814 
815  foreach(lc, nodes)
816  {
817  Expr *e = (Expr *) lfirst(lc);
818 
819  result = lappend(result, ExecPrepareExpr(e, estate));
820  }
821 
822  MemoryContextSwitchTo(oldcontext);
823 
824  return result;
825 }
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:732

References EState::es_query_cxt, ExecPrepareExpr(), lappend(), lfirst, MemoryContextSwitchTo(), and NIL.

Referenced by EvaluateParams(), FormIndexDatum(), FormPartitionKeyDatum(), and make_build_data().

◆ ExecPrepareQual()

ExprState* ExecPrepareQual ( List qual,
EState estate 
)

Definition at line 760 of file execExpr.c.

761 {
762  ExprState *result;
763  MemoryContext oldcontext;
764 
765  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
766 
767  qual = (List *) expression_planner((Expr *) qual);
768 
769  result = ExecInitQual(qual, NULL);
770 
771  MemoryContextSwitchTo(oldcontext);
772 
773  return result;
774 }
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:213

References EState::es_query_cxt, ExecInitQual(), expression_planner(), and MemoryContextSwitchTo().

Referenced by compute_index_stats(), ExecCheckIndexConstraints(), ExecInsertIndexTuples(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), and TriggerEnabled().

◆ ExecProcNode()

◆ ExecProject()

static TupleTableSlot* ExecProject ( ProjectionInfo projInfo)
inlinestatic

Definition at line 376 of file executor.h.

377 {
378  ExprContext *econtext = projInfo->pi_exprContext;
379  ExprState *state = &projInfo->pi_state;
380  TupleTableSlot *slot = state->resultslot;
381  bool isnull;
382 
383  /*
384  * Clear any former contents of the result slot. This makes it safe for
385  * us to use the slot's Datum/isnull arrays as workspace.
386  */
387  ExecClearTuple(slot);
388 
389  /* Run the expression, discarding scalar result from the last column. */
390  (void) ExecEvalExprSwitchContext(state, econtext, &isnull);
391 
392  /*
393  * Successfully formed a result row. Mark the result slot as containing a
394  * valid virtual tuple (inlined version of ExecStoreVirtualTuple()).
395  */
396  slot->tts_flags &= ~TTS_FLAG_EMPTY;
397  slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
398 
399  return slot;
400 }
AttrNumber tts_nvalid
Definition: tuptable.h:120
uint16 tts_flags
Definition: tuptable.h:118
#define TTS_FLAG_EMPTY
Definition: tuptable.h:95

References ExecClearTuple(), ExecEvalExprSwitchContext(), TupleDescData::natts, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TTS_FLAG_EMPTY, TupleTableSlot::tts_flags, TupleTableSlot::tts_nvalid, and TupleTableSlot::tts_tupleDescriptor.

Referenced by buildSubPlanHash(), ExecGather(), ExecGatherMerge(), ExecGetInsertNewTuple(), ExecGetUpdateNewTuple(), ExecGroup(), ExecHashJoinImpl(), ExecHashSubPlan(), ExecMergeJoin(), ExecMergeMatched(), ExecMergeNotMatched(), ExecNestLoop(), ExecOnConflictUpdate(), ExecProcessReturning(), ExecResult(), ExecScan(), ExecWindowAgg(), MJFillInner(), MJFillOuter(), and project_aggregates().

◆ ExecQual()

static bool ExecQual ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 413 of file executor.h.

414 {
415  Datum ret;
416  bool isnull;
417 
418  /* short-circuit (here and in ExecInitQual) for empty restriction list */
419  if (state == NULL)
420  return true;
421 
422  /* verify that expression was compiled using ExecInitQual */
423  Assert(state->flags & EEO_FLAG_IS_QUAL);
424 
425  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
426 
427  /* EEOP_QUAL should never return NULL */
428  Assert(!isnull);
429 
430  return DatumGetBool(ret);
431 }

References Assert(), DatumGetBool(), EEO_FLAG_IS_QUAL, and ExecEvalExprSwitchContext().

Referenced by agg_retrieve_direct(), compute_index_stats(), CopyFrom(), ExecCheckIndexConstraints(), ExecEvalPreOrderedDistinctMulti(), ExecGroup(), ExecHashJoinImpl(), ExecInsertIndexTuples(), ExecMergeJoin(), ExecMergeMatched(), ExecMergeNotMatched(), ExecNestLoop(), ExecOnConflictUpdate(), ExecQualAndReset(), ExecResult(), ExecScan(), ExecWindowAgg(), ExecWithCheckOptions(), ForeignRecheck(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), MemoizeHash_equal(), MJFillInner(), MJFillOuter(), process_ordered_aggregate_multi(), project_aggregates(), and TriggerEnabled().

◆ ExecQualAndReset()

static bool ExecQualAndReset ( ExprState state,
ExprContext econtext 
)
inlinestatic

◆ ExecRelationIsTargetRelation()

bool ExecRelationIsTargetRelation ( EState estate,
Index  scanrelid 
)

Definition at line 684 of file execUtils.c.

685 {
686  return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
687 }
bool list_member_int(const List *list, int datum)
Definition: list.c:702
List * resultRelations
Definition: plannodes.h:78

References EState::es_plannedstmt, list_member_int(), and PlannedStmt::resultRelations.

◆ ExecReScan()

void ExecReScan ( PlanState node)

Definition at line 76 of file execAmi.c.

77 {
78  /* If collecting timing stats, update them */
79  if (node->instrument)
80  InstrEndLoop(node->instrument);
81 
82  /*
83  * If we have changed parameters, propagate that info.
84  *
85  * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
86  * corresponding to the output param(s) that the InitPlan will update.
87  * Since we make only one pass over the list, that means that an InitPlan
88  * can depend on the output param(s) of a sibling InitPlan only if that
89  * sibling appears earlier in the list. This is workable for now given
90  * the limited ways in which one InitPlan could depend on another, but
91  * eventually we might need to work harder (or else make the planner
92  * enlarge the extParam/allParam sets to include the params of depended-on
93  * InitPlans).
94  */
95  if (node->chgParam != NULL)
96  {
97  ListCell *l;
98 
99  foreach(l, node->initPlan)
100  {
101  SubPlanState *sstate = (SubPlanState *) lfirst(l);
102  PlanState *splan = sstate->planstate;
103 
104  if (splan->plan->extParam != NULL) /* don't care about child
105  * local Params */
107  if (splan->chgParam != NULL)
108  ExecReScanSetParamPlan(sstate, node);
109  }
110  foreach(l, node->subPlan)
111  {
112  SubPlanState *sstate = (SubPlanState *) lfirst(l);
113  PlanState *splan = sstate->planstate;
114 
115  if (splan->plan->extParam != NULL)
117  }
118  /* Well. Now set chgParam for child trees. */
119  if (outerPlanState(node) != NULL)
121  if (innerPlanState(node) != NULL)
123  }
124 
125  /* Call expression callbacks */
126  if (node->ps_ExprContext)
128 
129  /* And do node-type-specific processing */
130  switch (nodeTag(node))
131  {
132  case T_ResultState:
133  ExecReScanResult((ResultState *) node);
134  break;
135 
136  case T_ProjectSetState:
138  break;
139 
140  case T_ModifyTableState:
142  break;
143 
144  case T_AppendState:
145  ExecReScanAppend((AppendState *) node);
146  break;
147 
148  case T_MergeAppendState:
150  break;
151 
152  case T_RecursiveUnionState:
154  break;
155 
156  case T_BitmapAndState:
158  break;
159 
160  case T_BitmapOrState:
162  break;
163 
164  case T_SeqScanState:
166  break;
167 
168  case T_SampleScanState:
170  break;
171 
172  case T_GatherState:
173  ExecReScanGather((GatherState *) node);
174  break;
175 
176  case T_GatherMergeState:
178  break;
179 
180  case T_IndexScanState:
182  break;
183 
184  case T_IndexOnlyScanState:
186  break;
187 
188  case T_BitmapIndexScanState:
190  break;
191 
192  case T_BitmapHeapScanState:
194  break;
195 
196  case T_TidScanState:
198  break;
199 
200  case T_TidRangeScanState:
202  break;
203 
204  case T_SubqueryScanState:
206  break;
207 
208  case T_FunctionScanState:
210  break;
211 
212  case T_TableFuncScanState:
214  break;
215 
216  case T_ValuesScanState:
218  break;
219 
220  case T_CteScanState:
222  break;
223 
224  case T_NamedTuplestoreScanState:
226  break;
227 
228  case T_WorkTableScanState:
230  break;
231 
232  case T_ForeignScanState:
234  break;
235 
236  case T_CustomScanState:
238  break;
239 
240  case T_NestLoopState:
242  break;
243 
244  case T_MergeJoinState:
246  break;
247 
248  case T_HashJoinState:
250  break;
251 
252  case T_MaterialState:
254  break;
255 
256  case T_MemoizeState:
258  break;
259 
260  case T_SortState:
261  ExecReScanSort((SortState *) node);
262  break;
263 
264  case T_IncrementalSortState:
266  break;
267 
268  case T_GroupState:
269  ExecReScanGroup((GroupState *) node);
270  break;
271 
272  case T_AggState:
273  ExecReScanAgg((AggState *) node);
274  break;
275 
276  case T_WindowAggState:
278  break;
279 
280  case T_UniqueState:
281  ExecReScanUnique((UniqueState *) node);
282  break;
283 
284  case T_HashState:
285  ExecReScanHash((HashState *) node);
286  break;
287 
288  case T_SetOpState:
289  ExecReScanSetOp((SetOpState *) node);
290  break;
291 
292  case T_LockRowsState:
294  break;
295 
296  case T_LimitState:
297  ExecReScanLimit((LimitState *) node);
298  break;
299 
300  default:
301  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
302  break;
303  }
304 
305  if (node->chgParam != NULL)
306  {
307  bms_free(node->chgParam);
308  node->chgParam = NULL;
309  }
310 }
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:441
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:844
#define innerPlanState(node)
Definition: execnodes.h:1138
void InstrEndLoop(Instrumentation *instr)
Definition: instrument.c:140
void ExecReScanAgg(AggState *node)
Definition: nodeAgg.c:4364
void ExecReScanAppend(AppendState *node)
Definition: nodeAppend.c:406
void ExecReScanBitmapAnd(BitmapAndState *node)
void ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
void ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
void ExecReScanBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:219
void ExecReScanCteScan(CteScanState *node)
Definition: nodeCtescan.c:307
void ExecReScanCustomScan(CustomScanState *node)
Definition: nodeCustom.c:132
void ExecReScanForeignScan(ForeignScanState *node)
void ExecReScanFunctionScan(FunctionScanState *node)
void ExecReScanGatherMerge(GatherMergeState *node)
void ExecReScanGather(GatherState *node)
Definition: nodeGather.c:435
void ExecReScanGroup(GroupState *node)
Definition: nodeGroup.c:235
void ExecReScanHash(HashState *node)
Definition: nodeHash.c:2353
void ExecReScanHashJoin(HashJoinState *node)
void ExecReScanIncrementalSort(IncrementalSortState *node)
void ExecReScanIndexOnlyScan(IndexOnlyScanState *node)
void ExecReScanIndexScan(IndexScanState *node)
void ExecReScanLimit(LimitState *node)
Definition: nodeLimit.c:541
void ExecReScanLockRows(LockRowsState *node)
Definition: nodeLockRows.c:394
void ExecReScanMaterial(MaterialState *node)
Definition: nodeMaterial.c:313
void ExecReScanMemoize(MemoizeState *node)
Definition: nodeMemoize.c:1139
void ExecReScanMergeAppend(MergeAppendState *node)
void ExecReScanMergeJoin(MergeJoinState *node)
void ExecReScanModifyTable(ModifyTableState *node)
void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
void ExecReScanNestLoop(NestLoopState *node)
Definition: nodeNestloop.c:381
void ExecReScanProjectSet(ProjectSetState *node)
void ExecReScanRecursiveUnion(RecursiveUnionState *node)
void ExecReScanResult(ResultState *node)
Definition: nodeResult.c:249
void ExecReScanSampleScan(SampleScanState *node)
void ExecReScanSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:212
void ExecReScanSetOp(SetOpState *node)
Definition: nodeSetOp.c:594
void ExecReScanSort(SortState *node)
Definition: nodeSort.c:362
void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
Definition: nodeSubplan.c:1291
void ExecReScanSubqueryScan(SubqueryScanState *node)
void ExecReScanTableFuncScan(TableFuncScanState *node)
void ExecReScanTidRangeScan(TidRangeScanState *node)
void ExecReScanTidScan(TidScanState *node)
Definition: nodeTidscan.c:447
void ExecReScanUnique(UniqueState *node)
Definition: nodeUnique.c:175
void ExecReScanValuesScan(ValuesScanState *node)
void ExecReScanWindowAgg(WindowAggState *node)
void ExecReScanWorkTableScan(WorkTableScanState *node)
static SPIPlanPtr splan
Definition: regress.c:269
List * subPlan
Definition: execnodes.h:1070
struct PlanState * planstate
Definition: execnodes.h:959

References bms_free(), PlanState::chgParam, elog, ERROR, ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapIndexScan(), ExecReScanBitmapOr(), ExecReScanCteScan(), ExecReScanCustomScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanGather(), ExecReScanGatherMerge(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanIncrementalSort(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMemoize(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanModifyTable(), ExecReScanNamedTuplestoreScan(), ExecReScanNestLoop(), ExecReScanProjectSet(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSampleScan(), ExecReScanSeqScan(), ExecReScanSetOp(), ExecReScanSetParamPlan(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanTableFuncScan(), ExecReScanTidRangeScan(), ExecReScanTidScan(), ExecReScanUnique(), ExecReScanValuesScan(), ExecReScanWindowAgg(), ExecReScanWorkTableScan(), PlanState::initPlan, innerPlanState, InstrEndLoop(), PlanState::instrument, lfirst, nodeTag, outerPlanState, SubPlanState::planstate, PlanState::ps_ExprContext, ReScanExprContext(), splan, PlanState::subPlan, and UpdateChangedParamSet().

Referenced by buildSubPlanHash(), ExecAsyncRequest(), ExecIndexOnlyScan(), ExecIndexScan(), ExecNestLoop(), ExecProcNode(), ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapOr(), ExecReScanForeignScan(), ExecReScanGather(), ExecReScanGatherMerge(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanIncrementalSort(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMemoize(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanNestLoop(), ExecReScanProjectSet(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSetOp(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanUnique(), ExecReScanWindowAgg(), ExecScanSubPlan(), ExecutorRewind(), MultiExecBitmapIndexScan(), and MultiExecProcNode().

◆ ExecRestrPos()

void ExecRestrPos ( PlanState node)

Definition at line 375 of file execAmi.c.

376 {
377  switch (nodeTag(node))
378  {
379  case T_IndexScanState:
381  break;
382 
383  case T_IndexOnlyScanState:
385  break;
386 
387  case T_CustomScanState:
389  break;
390 
391  case T_MaterialState:
393  break;
394 
395  case T_SortState:
396  ExecSortRestrPos((SortState *) node);
397  break;
398 
399  case T_ResultState:
401  break;
402 
403  default:
404  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
405  break;
406  }
407 }
void ExecCustomRestrPos(CustomScanState *node)
Definition: nodeCustom.c:150
void ExecIndexOnlyRestrPos(IndexOnlyScanState *node)
void ExecIndexRestrPos(IndexScanState *node)
void ExecMaterialRestrPos(MaterialState *node)
Definition: nodeMaterial.c:290
void ExecResultRestrPos(ResultState *node)
Definition: nodeResult.c:161
void ExecSortRestrPos(SortState *node)
Definition: nodeSort.c:347

References elog, ERROR, ExecCustomRestrPos(), ExecIndexOnlyRestrPos(), ExecIndexRestrPos(), ExecMaterialRestrPos(), ExecResultRestrPos(), ExecSortRestrPos(), and nodeTag.

Referenced by ExecMergeJoin(), and ExecResultRestrPos().

◆ ExecScan()

TupleTableSlot* ExecScan ( ScanState node,
ExecScanAccessMtd  accessMtd,
ExecScanRecheckMtd  recheckMtd 
)

Definition at line 156 of file execScan.c.

159 {
160  ExprContext *econtext;
161  ExprState *qual;
162  ProjectionInfo *projInfo;
163 
164  /*
165  * Fetch data from node
166  */
167  qual = node->ps.qual;
168  projInfo = node->ps.ps_ProjInfo;
169  econtext = node->ps.ps_ExprContext;
170 
171  /* interrupt checks are in ExecScanFetch */
172 
173  /*
174  * If we have neither a qual to check nor a projection to do, just skip
175  * all the overhead and return the raw scan tuple.
176  */
177  if (!qual && !projInfo)
178  {
179  ResetExprContext(econtext);
180  return ExecScanFetch(node, accessMtd, recheckMtd);
181  }
182 
183  /*
184  * Reset per-tuple memory context to free any expression evaluation
185  * storage allocated in the previous tuple cycle.
186  */
187  ResetExprContext(econtext);
188 
189  /*
190  * get a tuple from the access method. Loop until we obtain a tuple that
191  * passes the qualification.
192  */
193  for (;;)
194  {
195  TupleTableSlot *slot;
196 
197  slot = ExecScanFetch(node, accessMtd, recheckMtd);
198 
199  /*
200  * if the slot returned by the accessMtd contains NULL, then it means
201  * there is nothing more to scan so we just return an empty slot,
202  * being careful to use the projection result slot so it has correct
203  * tupleDesc.
204  */
205  if (TupIsNull(slot))
206  {
207  if (projInfo)
208  return ExecClearTuple(projInfo->pi_state.resultslot);
209  else
210  return slot;
211  }
212 
213  /*
214  * place the current tuple into the expr context
215  */
216  econtext->ecxt_scantuple = slot;
217 
218  /*
219  * check that the current tuple satisfies the qual-clause
220  *
221  * check for non-null qual here to avoid a function call to ExecQual()
222  * when the qual is null ... saves only a few cycles, but they add up
223  * ...
224  */
225  if (qual == NULL || ExecQual(qual, econtext))
226  {
227  /*
228  * Found a satisfactory scan tuple.
229  */
230  if (projInfo)
231  {
232  /*
233  * Form a projection tuple, store it in the result tuple slot
234  * and return it.
235  */
236  return ExecProject(projInfo);
237  }
238  else
239  {
240  /*
241  * Here, we aren't projecting, so just return scan tuple.
242  */
243  return slot;
244  }
245  }
246  else
247  InstrCountFiltered1(node, 1);
248 
249  /*
250  * Tuple fails qual, so free per-tuple memory and try again.
251  */
252  ResetExprContext(econtext);
253  }
254 }
static TupleTableSlot * ExecScanFetch(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:34
#define InstrCountFiltered1(node, delta)
Definition: execnodes.h:1147
TupleTableSlot * resultslot
Definition: execnodes.h:97
ExprState * qual
Definition: execnodes.h:1064

References ExprContext::ecxt_scantuple, ExecClearTuple(), ExecProject(), ExecQual(), ExecScanFetch(), InstrCountFiltered1, ProjectionInfo::pi_state, ScanState::ps, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::qual, ResetExprContext, ExprState::resultslot, and TupIsNull.

Referenced by ExecBitmapHeapScan(), ExecCteScan(), ExecForeignScan(), ExecFunctionScan(), ExecIndexOnlyScan(), ExecIndexScan(), ExecNamedTuplestoreScan(), ExecSampleScan(), ExecSeqScan(), ExecSubqueryScan(), ExecTableFuncScan(), ExecTidRangeScan(), ExecTidScan(), ExecValuesScan(), and ExecWorkTableScan().

◆ ExecScanReScan()

void ExecScanReScan ( ScanState node)

Definition at line 297 of file execScan.c.

298 {
299  EState *estate = node->ps.state;
300 
301  /*
302  * We must clear the scan tuple so that observers (e.g., execCurrent.c)
303  * can tell that this plan node is not positioned on a tuple.
304  */
306 
307  /*
308  * Rescan EvalPlanQual tuple(s) if we're inside an EvalPlanQual recheck.
309  * But don't lose the "blocked" status of blocked target relations.
310  */
311  if (estate->es_epq_active != NULL)
312  {
313  EPQState *epqstate = estate->es_epq_active;
314  Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
315 
316  if (scanrelid > 0)
317  epqstate->relsubs_done[scanrelid - 1] =
318  epqstate->relsubs_blocked[scanrelid - 1];
319  else
320  {
321  Bitmapset *relids;
322  int rtindex = -1;
323 
324  /*
325  * If an FDW or custom scan provider has replaced the join with a
326  * scan, there are multiple RTIs; reset the epqScanDone flag for
327  * all of them.
328  */
329  if (IsA(node->ps.plan, ForeignScan))
330  relids = ((ForeignScan *) node->ps.plan)->fs_base_relids;
331  else if (IsA(node->ps.plan, CustomScan))
332  relids = ((CustomScan *) node->ps.plan)->custom_relids;
333  else
334  elog(ERROR, "unexpected scan node: %d",
335  (int) nodeTag(node->ps.plan));
336 
337  while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
338  {
339  Assert(rtindex > 0);
340  epqstate->relsubs_done[rtindex - 1] =
341  epqstate->relsubs_blocked[rtindex - 1];
342  }
343  }
344  }
345 }
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
struct EPQState * es_epq_active
Definition: execnodes.h:697

References Assert(), bms_next_member(), elog, ERROR, EState::es_epq_active, ExecClearTuple(), IsA, nodeTag, PlanState::plan, ScanState::ps, EPQState::relsubs_blocked, EPQState::relsubs_done, ScanState::ss_ScanTupleSlot, and PlanState::state.

Referenced by ExecReScanBitmapHeapScan(), ExecReScanCteScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanNamedTuplestoreScan(), ExecReScanSampleScan(), ExecReScanSeqScan(), ExecReScanSubqueryScan(), ExecReScanTableFuncScan(), ExecReScanTidRangeScan(), ExecReScanTidScan(), ExecReScanValuesScan(), and ExecReScanWorkTableScan().

◆ ExecSetExecProcNode()

void ExecSetExecProcNode ( PlanState node,
ExecProcNodeMtd  function 
)

Definition at line 425 of file execProcnode.c.

426 {
427  /*
428  * Add a wrapper around the ExecProcNode callback that checks stack depth
429  * during the first execution and maybe adds an instrumentation wrapper.
430  * When the callback is changed after execution has already begun that
431  * means we'll superfluously execute ExecProcNodeFirst, but that seems ok.
432  */
433  node->ExecProcNodeReal = function;
435 }
static TupleTableSlot * ExecProcNodeFirst(PlanState *node)
Definition: execProcnode.c:443
ExecProcNodeMtd ExecProcNodeReal
Definition: execnodes.h:1050

References PlanState::ExecProcNode, ExecProcNodeFirst(), and PlanState::ExecProcNodeReal.

Referenced by ExecHashJoinInitializeDSM(), ExecHashJoinInitializeWorker(), and ExecInitNode().

◆ ExecSetTupleBound()

void ExecSetTupleBound ( int64  tuples_needed,
PlanState child_node 
)

Definition at line 843 of file execProcnode.c.

844 {
845  /*
846  * Since this function recurses, in principle we should check stack depth
847  * here. In practice, it's probably pointless since the earlier node
848  * initialization tree traversal would surely have consumed more stack.
849  */
850 
851  if (IsA(child_node, SortState))
852  {
853  /*
854  * If it is a Sort node, notify it that it can use bounded sort.
855  *
856  * Note: it is the responsibility of nodeSort.c to react properly to
857  * changes of these parameters. If we ever redesign this, it'd be a
858  * good idea to integrate this signaling with the parameter-change
859  * mechanism.
860  */
861  SortState *sortState = (SortState *) child_node;
862 
863  if (tuples_needed < 0)
864  {
865  /* make sure flag gets reset if needed upon rescan */
866  sortState->bounded = false;
867  }
868  else
869  {
870  sortState->bounded = true;
871  sortState->bound = tuples_needed;
872  }
873  }
874  else if (IsA(child_node, IncrementalSortState))
875  {
876  /*
877  * If it is an IncrementalSort node, notify it that it can use bounded
878  * sort.
879  *
880  * Note: it is the responsibility of nodeIncrementalSort.c to react
881  * properly to changes of these parameters. If we ever redesign this,
882  * it'd be a good idea to integrate this signaling with the
883  * parameter-change mechanism.
884  */
885  IncrementalSortState *sortState = (IncrementalSortState *) child_node;
886 
887  if (tuples_needed < 0)
888  {
889  /* make sure flag gets reset if needed upon rescan */
890  sortState->bounded = false;
891  }
892  else
893  {
894  sortState->bounded = true;
895  sortState->bound = tuples_needed;
896  }
897  }
898  else if (IsA(child_node, AppendState))
899  {
900  /*
901  * If it is an Append, we can apply the bound to any nodes that are
902  * children of the Append, since the Append surely need read no more
903  * than that many tuples from any one input.
904  */
905  AppendState *aState = (AppendState *) child_node;
906  int i;
907 
908  for (i = 0; i < aState->as_nplans; i++)
909  ExecSetTupleBound(tuples_needed, aState->appendplans[i]);
910  }
911  else if (IsA(child_node, MergeAppendState))
912  {
913  /*
914  * If it is a MergeAppend, we can apply the bound to any nodes that
915  * are children of the MergeAppend, since the MergeAppend surely need
916  * read no more than that many tuples from any one input.
917  */
918  MergeAppendState *maState = (MergeAppendState *) child_node;
919  int i;
920 
921  for (i = 0; i < maState->ms_nplans; i++)
922  ExecSetTupleBound(tuples_needed, maState->mergeplans[i]);
923  }
924  else if (IsA(child_node, ResultState))
925  {
926  /*
927  * Similarly, for a projecting Result, we can apply the bound to its
928  * child node.
929  *
930  * If Result supported qual checking, we'd have to punt on seeing a
931  * qual. Note that having a resconstantqual is not a showstopper: if
932  * that condition succeeds it affects nothing, while if it fails, no
933  * rows will be demanded from the Result child anyway.
934  */
935  if (outerPlanState(child_node))
936  ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
937  }
938  else if (IsA(child_node, SubqueryScanState))
939  {
940  /*
941  * We can also descend through SubqueryScan, but only if it has no
942  * qual (otherwise it might discard rows).
943  */
944  SubqueryScanState *subqueryState = (SubqueryScanState *) child_node;
945 
946  if (subqueryState->ss.ps.qual == NULL)
947  ExecSetTupleBound(tuples_needed, subqueryState->subplan);
948  }
949  else if (IsA(child_node, GatherState))
950  {
951  /*
952  * A Gather node can propagate the bound to its workers. As with
953  * MergeAppend, no one worker could possibly need to return more
954  * tuples than the Gather itself needs to.
955  *
956  * Note: As with Sort, the Gather node is responsible for reacting
957  * properly to changes to this parameter.
958  */
959  GatherState *gstate = (GatherState *) child_node;
960 
961  gstate->tuples_needed = tuples_needed;
962 
963  /* Also pass down the bound to our own copy of the child plan */
964  ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
965  }
966  else if (IsA(child_node, GatherMergeState))
967  {
968  /* Same comments as for Gather */
969  GatherMergeState *gstate = (GatherMergeState *) child_node;
970 
971  gstate->tuples_needed = tuples_needed;
972 
973  ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
974  }
975 
976  /*
977  * In principle we could descend through any plan node type that is
978  * certain not to discard or combine input rows; but on seeing a node that
979  * can do that, we can't propagate the bound any further. For the moment
980  * it's unclear that any other cases are worth checking here.
981  */
982 }
void ExecSetTupleBound(int64 tuples_needed, PlanState *child_node)
Definition: execProcnode.c:843
PlanState ** appendplans
Definition: execnodes.h:1359
int64 tuples_needed
Definition: execnodes.h:2594
PlanState ** mergeplans
Definition: execnodes.h:1403
bool bounded
Definition: execnodes.h:2255
int64 bound
Definition: execnodes.h:2256
PlanState * subplan
Definition: execnodes.h:1804

References AppendState::appendplans, AppendState::as_nplans, SortState::bound, IncrementalSortState::bound, SortState::bounded, IncrementalSortState::bounded, i, IsA, MergeAppendState::mergeplans, MergeAppendState::ms_nplans, outerPlanState, ScanState::ps, PlanState::qual, SubqueryScanState::ss, SubqueryScanState::subplan, GatherState::tuples_needed, and GatherMergeState::tuples_needed.

Referenced by ParallelQueryMain(), and recompute_limits().

◆ ExecShutdownNode()

void ExecShutdownNode ( PlanState node)

Definition at line 767 of file execProcnode.c.

768 {
769  (void) ExecShutdownNode_walker(node, NULL);
770 }
static bool ExecShutdownNode_walker(PlanState *node, void *context)
Definition: execProcnode.c:773

References ExecShutdownNode_walker().

Referenced by ExecutePlan().

◆ ExecSimpleRelationDelete()

void ExecSimpleRelationDelete ( ResultRelInfo resultRelInfo,
EState estate,
EPQState epqstate,
TupleTableSlot searchslot 
)

Definition at line 619 of file execReplication.c.

622 {
623  bool skip_tuple = false;
624  Relation rel = resultRelInfo->ri_RelationDesc;
625  ItemPointer tid = &searchslot->tts_tid;
626 
628 
629  /* BEFORE ROW DELETE Triggers */
630  if (resultRelInfo->ri_TrigDesc &&
631  resultRelInfo->ri_TrigDesc->trig_delete_before_row)
632  {
633  skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
634  tid, NULL, NULL, NULL, NULL);
635  }
636 
637  if (!skip_tuple)
638  {
639  /* OK, delete the tuple */
640  simple_table_tuple_delete(rel, tid, estate->es_snapshot);
641 
642  /* AFTER ROW DELETE Triggers */
643  ExecARDeleteTriggers(estate, resultRelInfo,
644  tid, NULL, NULL, false);
645  }
646 }
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:486
bool trig_delete_before_row
Definition: reltrigger.h:66
void simple_table_tuple_delete(Relation rel, ItemPointer tid, Snapshot snapshot)
Definition: tableam.c:290
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition: trigger.c:2774
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot **epqslot, TM_Result *tmresult, TM_FailureData *tmfd)
Definition: trigger.c:2683

References CheckCmdReplicaIdentity(), CMD_DELETE, EState::es_snapshot, ExecARDeleteTriggers(), ExecBRDeleteTriggers(), ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, simple_table_tuple_delete(), TriggerDesc::trig_delete_before_row, and TupleTableSlot::tts_tid.

Referenced by apply_handle_delete_internal().

◆ ExecSimpleRelationInsert()

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

Definition at line 490 of file execReplication.c.

492 {
493  bool skip_tuple = false;
494  Relation rel = resultRelInfo->ri_RelationDesc;
495 
496  /* For now we support only tables. */
497  Assert(rel->rd_rel->relkind == RELKIND_RELATION);
498 
500 
501  /* BEFORE ROW INSERT Triggers */
502  if (resultRelInfo->ri_TrigDesc &&
503  resultRelInfo->ri_TrigDesc->trig_insert_before_row)
504  {
505  if (!ExecBRInsertTriggers(estate, resultRelInfo, slot))
506  skip_tuple = true; /* "do nothing" */
507  }
508 
509  if (!skip_tuple)
510  {
511  List *recheckIndexes = NIL;
512 
513  /* Compute stored generated columns */
514  if (rel->rd_att->constr &&
516  ExecComputeStoredGenerated(resultRelInfo, estate, slot,
517  CMD_INSERT);
518 
519  /* Check the constraints of the tuple */
520  if (rel->rd_att->constr)
521  ExecConstraints(resultRelInfo, slot, estate);
522  if (rel->rd_rel->relispartition)
523  ExecPartitionCheck(resultRelInfo, slot, estate, true);
524 
525  /* OK, store the tuple and create index entries for it */
526  simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot);
527 
528  if (resultRelInfo->ri_NumIndices > 0)
529  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
530  slot, estate, false, false,
531  NULL, NIL, false);
532 
533  /* AFTER ROW INSERT Triggers */
534  ExecARInsertTriggers(estate, resultRelInfo, slot,
535  recheckIndexes, NULL);
536 
537  /*
538  * XXX we should in theory pass a TransitionCaptureState object to the
539  * above to capture transition tuples, but after statement triggers
540  * don't actually get fired by replication yet anyway
541  */
542 
543  list_free(recheckIndexes);
544  }
545 }
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
Definition: execIndexing.c:298
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1790
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1914
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
TupleDesc rd_att
Definition: rel.h:112
bool trig_insert_before_row
Definition: reltrigger.h:56
bool has_generated_stored
Definition: tupdesc.h:45
void simple_table_tuple_insert(Relation rel, TupleTableSlot *slot)
Definition: tableam.c:276
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2458
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2534

References Assert(), CheckCmdReplicaIdentity(), CMD_INSERT, TupleDescData::constr, ExecARInsertTriggers(), ExecBRInsertTriggers(), ExecComputeStoredGenerated(), ExecConstraints(), ExecInsertIndexTuples(), ExecPartitionCheck(), TupleConstr::has_generated_stored, list_free(), NIL, RelationData::rd_att, RelationData::rd_rel, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, simple_table_tuple_insert(), and TriggerDesc::trig_insert_before_row.

Referenced by apply_handle_insert_internal().

◆ ExecSimpleRelationUpdate()

void ExecSimpleRelationUpdate ( ResultRelInfo resultRelInfo,
EState estate,
EPQState epqstate,
TupleTableSlot searchslot,
TupleTableSlot slot 
)

Definition at line 554 of file execReplication.c.

557 {
558  bool skip_tuple = false;
559  Relation rel = resultRelInfo->ri_RelationDesc;
560  ItemPointer tid = &(searchslot->tts_tid);
561 
562  /* For now we support only tables. */
563  Assert(rel->rd_rel->relkind == RELKIND_RELATION);
564 
566 
567  /* BEFORE ROW UPDATE Triggers */
568  if (resultRelInfo->ri_TrigDesc &&
569  resultRelInfo->ri_TrigDesc->trig_update_before_row)
570  {
571  if (!ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
572  tid, NULL, slot, NULL, NULL))
573  skip_tuple = true; /* "do nothing" */
574  }
575 
576  if (!skip_tuple)
577  {
578  List *recheckIndexes = NIL;
579  TU_UpdateIndexes update_indexes;
580 
581  /* Compute stored generated columns */
582  if (rel->rd_att->constr &&
584  ExecComputeStoredGenerated(resultRelInfo, estate, slot,
585  CMD_UPDATE);
586 
587  /* Check the constraints of the tuple */
588  if (rel->rd_att->constr)
589  ExecConstraints(resultRelInfo, slot, estate);
590  if (rel->rd_rel->relispartition)
591  ExecPartitionCheck(resultRelInfo, slot, estate, true);
592 
593  simple_table_tuple_update(rel, tid, slot, estate->es_snapshot,
594  &update_indexes);
595 
596  if (resultRelInfo->ri_NumIndices > 0 && (update_indexes != TU_None))
597  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
598  slot, estate, true, false,
599  NULL, NIL,
600  (update_indexes == TU_Summarizing));
601 
602  /* AFTER ROW UPDATE Triggers */
603  ExecARUpdateTriggers(estate, resultRelInfo,
604  NULL, NULL,
605  tid, NULL, slot,
606  recheckIndexes, NULL, false);
607 
608  list_free(recheckIndexes);
609  }
610 }
bool trig_update_before_row
Definition: reltrigger.h:61
void simple_table_tuple_update(Relation rel, ItemPointer otid, TupleTableSlot *slot, Snapshot snapshot, TU_UpdateIndexes *update_indexes)
Definition: tableam.c:335
TU_UpdateIndexes
Definition: tableam.h:110
@ TU_Summarizing
Definition: tableam.h:118
@ TU_None
Definition: tableam.h:112
bool ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, TM_Result *tmresult, TM_FailureData *tmfd)
Definition: trigger.c:2934
void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, List *recheckIndexes, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition: trigger.c:3097

References Assert(), CheckCmdReplicaIdentity(), CMD_UPDATE, TupleDescData::constr, EState::es_snapshot, ExecARUpdateTriggers(), ExecBRUpdateTriggers(), ExecComputeStoredGenerated(), ExecConstraints(), ExecInsertIndexTuples(), ExecPartitionCheck(), TupleConstr::has_generated_stored, list_free(), NIL, RelationData::rd_att, RelationData::rd_rel, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, simple_table_tuple_update(), TriggerDesc::trig_update_before_row, TupleTableSlot::tts_tid, TU_None, and TU_Summarizing.

Referenced by apply_handle_tuple_routing(), and apply_handle_update_internal().

◆ ExecSupportsBackwardScan()

bool ExecSupportsBackwardScan ( Plan node)

Definition at line 510 of file execAmi.c.

511 {
512  if (node == NULL)
513  return false;
514 
515  /*
516  * Parallel-aware nodes return a subset of the tuples in each worker, and
517  * in general we can't expect to have enough bookkeeping state to know
518  * which ones we returned in this worker as opposed to some other worker.
519  */
520  if (node->parallel_aware)
521  return false;
522 
523  switch (nodeTag(node))
524  {
525  case T_Result:
526  if (outerPlan(node) != NULL)
527  return ExecSupportsBackwardScan(outerPlan(node));
528  else
529  return false;
530 
531  case T_Append:
532  {
533  ListCell *l;
534 
535  /* With async, tuples may be interleaved, so can't back up. */
536  if (((Append *) node)->nasyncplans > 0)
537  return false;
538 
539  foreach(l, ((Append *) node)->appendplans)
540  {
541  if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
542  return false;
543  }
544  /* need not check tlist because Append doesn't evaluate it */
545  return true;
546  }
547 
548  case T_SampleScan:
549  /* Simplify life for tablesample methods by disallowing this */
550  return false;
551 
552  case T_Gather:
553  return false;
554 
555  case T_IndexScan:
556  return IndexSupportsBackwardScan(((IndexScan *) node)->indexid);
557 
558  case T_IndexOnlyScan:
559  return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid);
560 
561  case T_SubqueryScan:
562  return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
563 
564  case T_CustomScan:
565  if (((CustomScan *) node)->flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN)
566  return true;
567  return false;
568 
569  case T_SeqScan:
570  case T_TidScan:
571  case T_TidRangeScan:
572  case T_FunctionScan:
573  case T_ValuesScan:
574  case T_CteScan:
575  case T_Material:
576  case T_Sort:
577  /* these don't evaluate tlist */
578  return true;
579 
580  case T_IncrementalSort:
581 
582  /*
583  * Unlike full sort, incremental sort keeps only a single group of
584  * tuples in memory, so it can't scan backwards.
585  */
586  return false;
587 
588  case T_LockRows:
589  case T_Limit:
590  return ExecSupportsBackwardScan(outerPlan(node));
591 
592  default:
593  return false;
594  }
595 }
static bool IndexSupportsBackwardScan(Oid indexid)
Definition: execAmi.c:602
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:510
#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN
Definition: extensible.h:84
bool parallel_aware
Definition: plannodes.h:140

References CUSTOMPATH_SUPPORT_BACKWARD_SCAN, IndexSupportsBackwardScan(), lfirst, nodeTag, outerPlan, and Plan::parallel_aware.

Referenced by PerformCursorOpen(), SPI_cursor_open_internal(), and standard_planner().

◆ ExecSupportsMarkRestore()

bool ExecSupportsMarkRestore ( struct Path pathnode)

Definition at line 417 of file execAmi.c.

418 {
419  /*
420  * For consistency with the routines above, we do not examine the nodeTag
421  * but rather the pathtype, which is the Plan node type the Path would
422  * produce.
423  */
424  switch (pathnode->pathtype)
425  {
426  case T_IndexScan:
427  case T_IndexOnlyScan:
428 
429  /*
430  * Not all index types support mark/restore.
431  */
432  return castNode(IndexPath, pathnode)->indexinfo->amcanmarkpos;
433 
434  case T_Material:
435  case T_Sort:
436  return true;
437 
438  case T_CustomScan:
439  if (castNode(CustomPath, pathnode)->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
440  return true;
441  return false;
442 
443  case T_Result:
444 
445  /*
446  * Result supports mark/restore iff it has a child plan that does.
447  *
448  * We have to be careful here because there is more than one Path
449  * type that can produce a Result plan node.
450  */
451  if (IsA(pathnode, ProjectionPath))
452  return ExecSupportsMarkRestore(((ProjectionPath *) pathnode)->subpath);
453  else if (IsA(pathnode, MinMaxAggPath))
454  return false; /* childless Result */
455  else if (IsA(pathnode, GroupResultPath))
456  return false; /* childless Result */
457  else
458  {
459  /* Simple RTE_RESULT base relation */
460  Assert(IsA(pathnode, Path));
461  return false; /* childless Result */
462  }
463 
464  case T_Append:
465  {
466  AppendPath *appendPath = castNode(AppendPath, pathnode);
467 
468  /*
469  * If there's exactly one child, then there will be no Append
470  * in the final plan, so we can handle mark/restore if the
471  * child plan node can.
472  */
473  if (list_length(appendPath->subpaths) == 1)
474  return ExecSupportsMarkRestore((Path *) linitial(appendPath->subpaths));
475  /* Otherwise, Append can't handle it */
476  return false;
477  }
478 
479  case T_MergeAppend:
480  {
481  MergeAppendPath *mapath = castNode(MergeAppendPath, pathnode);
482 
483  /*
484  * Like the Append case above, single-subpath MergeAppends
485  * won't be in the final plan, so just return the child's
486  * mark/restore ability.
487  */
488  if (list_length(mapath->subpaths) == 1)
489  return ExecSupportsMarkRestore((Path *) linitial(mapath->subpaths));
490  /* Otherwise, MergeAppend can't handle it */
491  return false;
492  }
493 
494  default:
495  break;
496  }
497 
498  return false;
499 }
bool ExecSupportsMarkRestore(Path *pathnode)
Definition: execAmi.c:417
#define CUSTOMPATH_SUPPORT_MARK_RESTORE
Definition: extensible.h:85
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:241
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define linitial(l)
Definition: pg_list.h:178
List * subpaths
Definition: pathnodes.h:1912
NodeTag pathtype
Definition: pathnodes.h:1606

References Assert(), castNode, CUSTOMPATH_SUPPORT_MARK_RESTORE, IsA, linitial, list_length(), Path::pathtype, subpath(), AppendPath::subpaths, and MergeAppendPath::subpaths.

Referenced by final_cost_mergejoin().

◆ ExecTargetListLength()

int ExecTargetListLength ( List targetlist)

Definition at line 1109 of file execUtils.c.

1110 {
1111  /* This used to be more complex, but fjoins are dead */
1112  return list_length(targetlist);
1113 }

References list_length().

Referenced by ExecTypeFromTLInternal().

◆ execTuplesHashPrepare()

void execTuplesHashPrepare ( int  numCols,
const Oid eqOperators,
Oid **  eqFuncOids,
FmgrInfo **  hashFunctions 
)

Definition at line 95 of file execGrouping.c.

99 {
100  int i;
101 
102  *eqFuncOids = (Oid *) palloc(numCols * sizeof(Oid));
103  *hashFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
104 
105  for (i = 0; i < numCols; i++)
106  {
107  Oid eq_opr = eqOperators[i];
108  Oid eq_function;
109  Oid left_hash_function;
110  Oid right_hash_function;
111 
112  eq_function = get_opcode(eq_opr);
113  if (!get_op_hash_functions(eq_opr,
114  &left_hash_function, &right_hash_function))
115  elog(ERROR, "could not find hash function for hash operator %u",
116  eq_opr);
117  /* We're not supporting cross-type cases here */
118  Assert(left_hash_function == right_hash_function);
119  (*eqFuncOids)[i] = eq_function;
120  fmgr_info(right_hash_function, &(*hashFunctions)[i]);
121  }
122 }
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1263
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:510

References Assert(), elog, ERROR, fmgr_info(), get_op_hash_functions(), get_opcode(), i, and palloc().

Referenced by ExecInitRecursiveUnion(), ExecInitSetOp(), and find_hash_columns().

◆ execTuplesMatchPrepare()

ExprState* execTuplesMatchPrepare ( TupleDesc  desc,
int  numCols,
const AttrNumber keyColIdx,
const Oid eqOperators,
const Oid collations,
PlanState parent 
)

Definition at line 58 of file execGrouping.c.

64 {
65  Oid *eqFunctions = (Oid *) palloc(numCols * sizeof(Oid));
66  int i;
67  ExprState *expr;
68 
69  if (numCols == 0)
70  return NULL;
71 
72  /* lookup equality functions */
73  for (i = 0; i < numCols; i++)
74  eqFunctions[i] = get_opcode(eqOperators[i]);
75 
76  /* build actual expression */
77  expr = ExecBuildGroupingEqual(desc, desc, NULL, NULL,
78  numCols, keyColIdx, eqFunctions, collations,
79  parent);
80 
81  return expr;
82 }

References ExecBuildGroupingEqual(), get_opcode(), i, and palloc().

Referenced by build_pertrans_for_aggref(), ExecInitAgg(), ExecInitGroup(), ExecInitLimit(), ExecInitSetOp(), ExecInitUnique(), ExecInitWindowAgg(), and hypothetical_dense_rank_final().

◆ ExecTypeFromExprList()

TupleDesc ExecTypeFromExprList ( List exprList)

Definition at line 1996 of file execTuples.c.

1997 {
1998  TupleDesc typeInfo;
1999  ListCell *lc;
2000  int cur_resno = 1;
2001 
2002  typeInfo = CreateTemplateTupleDesc(list_length(exprList));
2003 
2004  foreach(lc, exprList)
2005  {
2006  Node *e = lfirst(lc);
2007 
2008  TupleDescInitEntry(typeInfo,
2009  cur_resno,
2010  NULL,
2011  exprType(e),
2012  exprTypmod(e),
2013  0);
2014  TupleDescInitEntryCollation(typeInfo,
2015  cur_resno,
2016  exprCollation(e));
2017  cur_resno++;
2018  }
2019 
2020  return typeInfo;
2021 }
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:284
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:788
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:833

References CreateTemplateTupleDesc(), exprCollation(), exprType(), exprTypmod(), lfirst, list_length(), TupleDescInitEntry(), and TupleDescInitEntryCollation().

Referenced by ExecInitExprRec(), ExecInitMemoize(), and ExecInitValuesScan().

◆ ExecTypeFromTL()

TupleDesc ExecTypeFromTL ( List targetList)

◆ ExecTypeSetColNames()

void ExecTypeSetColNames ( TupleDesc  typeInfo,
List namesList 
)

Definition at line 2029 of file execTuples.c.

2030 {
2031  int colno = 0;
2032  ListCell *lc;
2033 
2034  /* It's only OK to change col names in a not-yet-blessed RECORD type */
2035  Assert(typeInfo->tdtypeid == RECORDOID);
2036  Assert(typeInfo->tdtypmod < 0);
2037 
2038  foreach(lc, namesList)
2039  {
2040  char *cname = strVal(lfirst(lc));
2041  Form_pg_attribute attr;
2042 
2043  /* Guard against too-long names list (probably can't happen) */
2044  if (colno >= typeInfo->natts)
2045  break;
2046  attr = TupleDescAttr(typeInfo, colno);
2047  colno++;
2048 
2049  /*
2050  * Do nothing for empty aliases or dropped columns (these cases
2051  * probably can't arise in RECORD types, either)
2052  */
2053  if (cname[0] == '\0' || attr->attisdropped)
2054  continue;
2055 
2056  /* OK, assign the column name */
2057  namestrcpy(&(attr->attname), cname);
2058  }
2059 }
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define strVal(v)
Definition: value.h:82

References Assert(), lfirst, namestrcpy(), TupleDescData::natts, strVal, TupleDescData::tdtypeid, TupleDescData::tdtypmod, and TupleDescAttr.

Referenced by ExecEvalWholeRowVar(), and ExecInitExprRec().

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2349 of file execMain.c.

2350 {
2351  Bitmapset *keyCols;
2352  Bitmapset *updatedCols;
2353 
2354  /*
2355  * Compute lock mode to use. If columns that are part of the key have not
2356  * been modified, then we can use a weaker lock, allowing for better
2357  * concurrency.
2358  */
2359  updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2360  keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2362 
2363  if (bms_overlap(keyCols, updatedCols))
2364  return LockTupleExclusive;
2365 
2366  return LockTupleNoKeyExclusive;
2367 }
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1324
@ LockTupleExclusive
Definition: lockoptions.h:58
@ LockTupleNoKeyExclusive
Definition: lockoptions.h:56
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:5220
@ INDEX_ATTR_BITMAP_KEY
Definition: relcache.h:61

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

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

◆ executor_errposition()

int executor_errposition ( EState estate,
int  location 
)

Definition at line 870 of file execUtils.c.

871 {
872  int pos;
873 
874  /* No-op if location was not provided */
875  if (location < 0)
876  return 0;
877  /* Can't do anything if source text is not available */
878  if (estate == NULL || estate->es_sourceText == NULL)
879  return 0;
880  /* Convert offset to character number */
881  pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
882  /* And pass it to the ereport mechanism */
883  return errposition(pos);
884 }
int errposition(int cursorpos)
Definition: elog.c:1448
int pg_mbstrlen_with_len(const char *mbstr, int limit)
Definition: mbutils.c:1057

References errposition(), EState::es_sourceText, and pg_mbstrlen_with_len().

Referenced by ExecInitFunc(), ExecInitSubscriptingRef(), and init_sexpr().

◆ ExecutorEnd()

void ExecutorEnd ( QueryDesc queryDesc)

Definition at line 467 of file execMain.c.

468 {
469  if (ExecutorEnd_hook)
470  (*ExecutorEnd_hook) (queryDesc);
471  else
472  standard_ExecutorEnd(queryDesc);
473 }
ExecutorEnd_hook_type ExecutorEnd_hook
Definition: execMain.c:68
void standard_ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:476

References ExecutorEnd_hook, and standard_ExecutorEnd().

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

◆ ExecutorFinish()

void ExecutorFinish ( QueryDesc queryDesc)

Definition at line 407 of file execMain.c.

408 {
410  (*ExecutorFinish_hook) (queryDesc);
411  else
412  standard_ExecutorFinish(queryDesc);
413 }
ExecutorFinish_hook_type ExecutorFinish_hook
Definition: execMain.c:67
void standard_ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:416

References ExecutorFinish_hook, and standard_ExecutorFinish().

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

◆ ExecutorRewind()

void ExecutorRewind ( QueryDesc queryDesc)

Definition at line 533 of file execMain.c.

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

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

Referenced by DoPortalRewind(), and PersistHoldablePortal().

◆ ExecutorRun()

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

Definition at line 297 of file execMain.c.

300 {
301  if (ExecutorRun_hook)
302  (*ExecutorRun_hook) (queryDesc, direction, count, execute_once);
303  else
304  standard_ExecutorRun(queryDesc, direction, count, execute_once);
305 }
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:308
ExecutorRun_hook_type ExecutorRun_hook
Definition: execMain.c:66

References ExecutorRun_hook, and standard_ExecutorRun().

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

◆ ExecutorStart()

void ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 124 of file execMain.c.

125 {
126  /*
127  * In some cases (e.g. an EXECUTE statement) a query execution will skip
128  * parse analysis, which means that the query_id won't be reported. Note
129  * that it's harmless to report the query_id multiple times, as the call
130  * will be ignored if the top level query_id has already been reported.
131  */
132  pgstat_report_query_id(queryDesc->plannedstmt->queryId, false);
133 
134  if (ExecutorStart_hook)
135  (*ExecutorStart_hook) (queryDesc, eflags);
136  else
137  standard_ExecutorStart(queryDesc, eflags);
138 }
void pgstat_report_query_id(uint64 query_id, bool force)
ExecutorStart_hook_type ExecutorStart_hook
Definition: execMain.c:65
void standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:141
uint64 queryId
Definition: plannodes.h:54
PlannedStmt * plannedstmt
Definition: execdesc.h:37

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

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

◆ ExecWithCheckOptions()

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

Definition at line 2049 of file execMain.c.

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

References bms_union(), build_attrmap_by_name_if_req(), ExprContext::ecxt_scantuple, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecBuildSlotValueDescription(), ExecGetInsertedCols(), ExecGetUpdatedCols(), ExecQual(), execute_attr_map_slot(), forboth, GetPerTupleExprContext, WithCheckOption::kind, lfirst, MakeTupleTableSlot(), WithCheckOption::polname, RelationGetDescr, RelationGetRelid, WithCheckOption::relname, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, ResultRelInfo::ri_WithCheckOptionExprs, ResultRelInfo::ri_WithCheckOptions, TTSOpsVirtual, WCO_RLS_CONFLICT_CHECK, WCO_RLS_INSERT_CHECK, WCO_RLS_MERGE_DELETE_CHECK, WCO_RLS_MERGE_UPDATE_CHECK, WCO_RLS_UPDATE_CHECK, and WCO_VIEW_CHECK.

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

◆ FindTupleHashEntry()

TupleHashEntry FindTupleHashEntry ( TupleHashTable  hashtable,
TupleTableSlot slot,
ExprState eqcomp,
FmgrInfo hashfunctions 
)

Definition at line 392 of file execGrouping.c.

395 {
396  TupleHashEntry entry;
397  MemoryContext oldContext;
399 
400  /* Need to run the hash functions in short-lived context */
401  oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
402 
403  /* Set up data needed by hash and match functions */
404  hashtable->inputslot = slot;
405  hashtable->in_hash_funcs = hashfunctions;
406  hashtable->cur_eq_func = eqcomp;
407 
408  /* Search the hash table */
409  key = NULL; /* flag to reference inputslot */
410  entry = tuplehash_lookup(hashtable->hashtab, key);
411  MemoryContextSwitchTo(oldContext);
412 
413  return entry;
414 }

References TupleHashTableData::cur_eq_func, TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, sort-test::key, MemoryContextSwitchTo(), and TupleHashTableData::tempcxt.

Referenced by ExecHashSubPlan().

◆ FreeExecutorState()

void FreeExecutorState ( EState estate)

Definition at line 189 of file execUtils.c.

190 {
191  /*
192  * Shut down and free any remaining ExprContexts. We do this explicitly
193  * to ensure that any remaining shutdown callbacks get called (since they
194  * might need to release resources that aren't simply memory within the
195  * per-query memory context).
196  */
197  while (estate->es_exprcontexts)
198  {
199  /*
200  * XXX: seems there ought to be a faster way to implement this than
201  * repeated list_delete(), no?
202  */
204  true);
205  /* FreeExprContext removed the list link for us */
206  }
207 
208  /* release JIT context, if allocated */
209  if (estate->es_jit)
210  {
211  jit_release_context(estate->es_jit);
212  estate->es_jit = NULL;
213  }
214 
215  /* release partition directory, if allocated */
216  if (estate->es_partition_directory)
217  {
219  estate->es_partition_directory = NULL;
220  }
221 
222  /*
223  * Free the per-query memory context, thereby releasing all working
224  * memory, including the EState node itself.
225  */
227 }
void FreeExprContext(ExprContext *econtext, bool isCommit)
Definition: execUtils.c:414
void jit_release_context(JitContext *context)
Definition: jit.c:137
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:442
void DestroyPartitionDirectory(PartitionDirectory pdir)
Definition: partdesc.c:442
PartitionDirectory es_partition_directory
Definition: execnodes.h:647

References DestroyPartitionDirectory(), EState::es_exprcontexts, EState::es_jit, EState::es_partition_directory, EState::es_query_cxt, FreeExprContext(), jit_release_context(), linitial, and MemoryContextDelete().

Referenced by afterTriggerInvokeEvents(), ATRewriteTable(), check_default_partition_contents(), compute_expr_stats(), compute_index_stats(), CopyFrom(), EvalPlanQualEnd(), evaluate_expr(), ExecuteCallStmt(), ExecuteQuery(), ExecuteTruncateGuts(), ExplainExecuteQuery(), finish_edata(), freestate_cluster(), get_qual_for_range(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), make_build_data(), operator_predicate_proof(), plpgsql_inline_handler(), plpgsql_xact_cb(), standard_ExecutorEnd(), StoreAttrDefault(), and validateDomainConstraint().

◆ FreeExprContext()

void FreeExprContext ( ExprContext econtext,
bool  isCommit 
)

Definition at line 414 of file execUtils.c.

415 {
416  EState *estate;
417 
418  /* Call any registered callbacks */
419  ShutdownExprContext(econtext, isCommit);
420  /* And clean up the memory used */
422  /* Unlink self from owning EState, if any */
423  estate = econtext->ecxt_estate;
424  if (estate)
426  econtext);
427  /* And delete the ExprContext node */
428  pfree(econtext);
429 }
static void ShutdownExprContext(ExprContext *econtext, bool isCommit)
Definition: execUtils.c:954
List * list_delete_ptr(List *list, void *datum)
Definition: list.c:872

References ExprContext::ecxt_estate, ExprContext::ecxt_per_tuple_memory, EState::es_exprcontexts, list_delete_ptr(), MemoryContextDelete(), pfree(), and ShutdownExprContext().

Referenced by FreeExecutorState(), plpgsql_destroy_econtext(), and plpgsql_subxact_cb().

◆ get_equal_strategy_number_for_am()

StrategyNumber get_equal_strategy_number_for_am ( Oid  am)

Definition at line 49 of file execReplication.c.

50 {
51  int ret;
52 
53  switch (am)
54  {
55  case BTREE_AM_OID:
57  break;
58  case HASH_AM_OID:
60  break;
61  default:
62  /* XXX: Only Btree and Hash indexes are supported */
63  ret = InvalidStrategy;
64  break;
65  }
66 
67  return ret;
68 }
#define InvalidStrategy
Definition: stratnum.h:24
#define HTEqualStrategyNumber
Definition: stratnum.h:41
#define BTEqualStrategyNumber
Definition: stratnum.h:31

References BTEqualStrategyNumber, HTEqualStrategyNumber, and InvalidStrategy.

Referenced by get_equal_strategy_number(), and IsIndexUsableForReplicaIdentityFull().

◆ GetAttributeByName()

Datum GetAttributeByName ( HeapTupleHeader  tuple,
const char *  attname,
bool isNull 
)

Definition at line 995 of file execUtils.c.

996 {
997  AttrNumber attrno;
998  Datum result;
999  Oid tupType;
1000  int32 tupTypmod;
1001  TupleDesc tupDesc;
1002  HeapTupleData tmptup;
1003  int i;
1004 
1005  if (attname == NULL)
1006  elog(ERROR, "invalid attribute name");
1007 
1008  if (isNull == NULL)
1009  elog(ERROR, "a NULL isNull pointer was passed");
1010 
1011  if (tuple == NULL)
1012  {
1013  /* Kinda bogus but compatible with old behavior... */
1014  *isNull = true;
1015  return (Datum) 0;
1016  }
1017 
1018  tupType = HeapTupleHeaderGetTypeId(tuple);
1019  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
1020  tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1021 
1022  attrno = InvalidAttrNumber;
1023  for (i = 0; i < tupDesc->natts; i++)
1024  {
1025  Form_pg_attribute att = TupleDescAttr(tupDesc, i);
1026 
1027  if (namestrcmp(&(att->attname), attname) == 0)
1028  {
1029  attrno = att->attnum;
1030  break;
1031  }
1032  }
1033 
1034  if (attrno == InvalidAttrNumber)
1035  elog(ERROR, "attribute \"%s\" does not exist", attname);
1036 
1037  /*
1038  * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1039  * the fields in the struct just in case user tries to inspect system
1040  * columns.
1041  */
1042  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1043  ItemPointerSetInvalid(&(tmptup.t_self));
1044  tmptup.t_tableOid = InvalidOid;
1045  tmptup.t_data = tuple;
1046 
1047  result = heap_getattr(&tmptup,
1048  attrno,
1049  tupDesc,
1050  isNull);
1051 
1052  ReleaseTupleDesc(tupDesc);
1053 
1054  return result;
1055 }
signed int int32
Definition: c.h:481
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
int namestrcmp(Name name, const char *str)
Definition: name.c:247
NameData attname
Definition: pg_attribute.h:41
ItemPointerData t_self
Definition: htup.h:65
Oid t_tableOid
Definition: htup.h:66
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1833

References attname, elog, ERROR, heap_getattr(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, InvalidAttrNumber, InvalidOid, ItemPointerSetInvalid(), lookup_rowtype_tupdesc(), namestrcmp(), TupleDescData::natts, ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, and TupleDescAttr.

Referenced by c_overpaid(), and overpaid().

◆ GetAttributeByNum()

Datum GetAttributeByNum ( HeapTupleHeader  tuple,
AttrNumber  attrno,
bool isNull 
)

Definition at line 1058 of file execUtils.c.

1061 {
1062  Datum result;
1063  Oid tupType;
1064  int32 tupTypmod;
1065  TupleDesc tupDesc;
1066  HeapTupleData tmptup;
1067 
1068  if (!AttributeNumberIsValid(attrno))
1069  elog(ERROR, "invalid attribute number %d", attrno);
1070 
1071  if (isNull == NULL)
1072  elog(ERROR, "a NULL isNull pointer was passed");
1073 
1074  if (tuple == NULL)
1075  {
1076  /* Kinda bogus but compatible with old behavior... */
1077  *isNull = true;
1078  return (Datum) 0;
1079  }
1080 
1081  tupType = HeapTupleHeaderGetTypeId(tuple);
1082  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
1083  tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1084 
1085  /*
1086  * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1087  * the fields in the struct just in case user tries to inspect system
1088  * columns.
1089  */
1090  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1091  ItemPointerSetInvalid(&(tmptup.t_self));
1092  tmptup.t_tableOid = InvalidOid;
1093  tmptup.t_data = tuple;
1094 
1095  result = heap_getattr(&tmptup,
1096  attrno,
1097  tupDesc,
1098  isNull);
1099 
1100  ReleaseTupleDesc(tupDesc);
1101 
1102  return result;
1103 }

References AttributeNumberIsValid, elog, ERROR, heap_getattr(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, InvalidOid, ItemPointerSetInvalid(), lookup_rowtype_tupdesc(), ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

◆ InitResultRelInfo()

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

Definition at line 1199 of file execMain.c.

1204 {
1205  MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1206  resultRelInfo->type = T_ResultRelInfo;
1207  resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1208  resultRelInfo->ri_RelationDesc = resultRelationDesc;
1209  resultRelInfo->ri_NumIndices = 0;
1210  resultRelInfo->ri_IndexRelationDescs = NULL;
1211  resultRelInfo->ri_IndexRelationInfo = NULL;
1212  /* make a copy so as not to depend on relcache info not changing... */
1213  resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1214  if (resultRelInfo->ri_TrigDesc)
1215  {
1216  int n = resultRelInfo->ri_TrigDesc->numtriggers;
1217 
1218  resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1219  palloc0(n * sizeof(FmgrInfo));
1220  resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1221  palloc0(n * sizeof(ExprState *));
1222  if (instrument_options)
1223  resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options, false);
1224  }
1225  else
1226  {
1227  resultRelInfo->ri_TrigFunctions = NULL;
1228  resultRelInfo->ri_TrigWhenExprs = NULL;
1229  resultRelInfo->ri_TrigInstrument = NULL;
1230  }
1231  if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1232  resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
1233  else
1234  resultRelInfo->ri_FdwRoutine = NULL;
1235 
1236  /* The following fields are set later if needed */
1237  resultRelInfo->ri_RowIdAttNo = 0;
1238  resultRelInfo->ri_extraUpdatedCols = NULL;
1239  resultRelInfo->ri_projectNew = NULL;
1240  resultRelInfo->ri_newTupleSlot = NULL;
1241  resultRelInfo->ri_oldTupleSlot = NULL;
1242  resultRelInfo->ri_projectNewInfoValid = false;
1243  resultRelInfo->ri_FdwState = NULL;
1244  resultRelInfo->ri_usesFdwDirectModify = false;
1245  resultRelInfo->ri_ConstraintExprs = NULL;
1246  resultRelInfo->ri_GeneratedExprsI = NULL;
1247  resultRelInfo->ri_GeneratedExprsU = NULL;
1248  resultRelInfo->ri_projectReturning = NULL;
1249  resultRelInfo->ri_onConflictArbiterIndexes = NIL;
1250  resultRelInfo->ri_onConflict = NULL;
1251  resultRelInfo->ri_ReturningSlot = NULL;
1252  resultRelInfo->ri_TrigOldSlot = NULL;
1253  resultRelInfo->ri_TrigNewSlot = NULL;
1254  resultRelInfo->ri_matchedMergeAction = NIL;
1255  resultRelInfo->ri_notMatchedMergeAction = NIL;
1256 
1257  /*
1258  * Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
1259  * non-NULL partition_root_rri. For child relations that are part of the
1260  * initial query rather than being dynamically added by tuple routing,
1261  * this field is filled in ExecInitModifyTable().
1262  */
1263  resultRelInfo->ri_RootResultRelInfo = partition_root_rri;
1264  /* Set by ExecGetRootToChildMap */
1265  resultRelInfo->ri_RootToChildMap = NULL;
1266  resultRelInfo->ri_RootToChildMapValid = false;
1267  /* Set by ExecInitRoutingInfo */
1268  resultRelInfo->ri_PartitionTupleSlot = NULL;
1269  resultRelInfo->ri_ChildToRootMap = NULL;
1270  resultRelInfo->ri_ChildToRootMapValid = false;
1271  resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
1272 }
#define MemSet(start, val, len)
Definition: c.h:1007
TriggerDesc * trigdesc
Definition: rel.h:117
List * ri_matchedMergeAction
Definition: execnodes.h:548
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:581
List * ri_notMatchedMergeAction
Definition: execnodes.h:549
OnConflictSetState * ri_onConflict
Definition: execnodes.h:545
List * ri_onConflictArbiterIndexes
Definition: execnodes.h:542
ExprState ** ri_ConstraintExprs
Definition: execnodes.h:525
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:495
TupleTableSlot * ri_oldTupleSlot
Definition: execnodes.h:481
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:584
ExprState ** ri_GeneratedExprsI
Definition: execnodes.h:528
void * ri_FdwState
Definition: execnodes.h:506
TupleTableSlot * ri_newTupleSlot
Definition: execnodes.h:479
NodeTag type
Definition: execnodes.h:450
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:539
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:492
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:489
bool ri_usesFdwDirectModify
Definition: execnodes.h:509
AttrNumber ri_RowIdAttNo
Definition: execnodes.h:471
int numtriggers
Definition: reltrigger.h:50
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:2085

References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), MemSet, NIL, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, ResultRelInfo::ri_ChildToRootMap, ResultRelInfo::ri_ChildToRootMapValid, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_extraUpdatedCols, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_GeneratedExprsI, ResultRelInfo::ri_GeneratedExprsU, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_matchedMergeAction, ResultRelInfo::ri_newTupleSlot, ResultRelInfo::ri_notMatchedMergeAction, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_oldTupleSlot, ResultRelInfo::ri_onConflict, ResultRelInfo::ri_onConflictArbiterIndexes, ResultRelInfo::ri_PartitionTupleSlot, ResultRelInfo::ri_projectNew, ResultRelInfo::ri_projectNewInfoValid, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RangeTableIndex, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_ReturningSlot, ResultRelInfo::ri_RootResultRelInfo, ResultRelInfo::ri_RootToChildMap, ResultRelInfo::ri_RootToChildMapValid, ResultRelInfo::ri_RowIdAttNo, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, ResultRelInfo::ri_TrigNewSlot, ResultRelInfo::ri_TrigOldSlot, ResultRelInfo::ri_TrigWhenExprs, ResultRelInfo::ri_usesFdwDirectModify, RelationData::trigdesc, and ResultRelInfo::type.

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

◆ LookupTupleHashEntry()

TupleHashEntry LookupTupleHashEntry ( TupleHashTable  hashtable,
TupleTableSlot slot,
bool isnew,
uint32 hash 
)

Definition at line 305 of file execGrouping.c.

307 {
308  TupleHashEntry entry;
309  MemoryContext oldContext;
310  uint32 local_hash;
311 
312  /* Need to run the hash functions in short-lived context */
313  oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
314 
315  /* set up data needed by hash and match functions */
316  hashtable->inputslot = slot;
317  hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
318  hashtable->cur_eq_func = hashtable->tab_eq_func;
319 
320  local_hash = TupleHashTableHash_internal(hashtable->hashtab, NULL);
321  entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, local_hash);
322 
323  if (hash != NULL)
324  *hash = local_hash;
325 
326  Assert(entry == NULL || entry->hash == local_hash);
327 
328  MemoryContextSwitchTo(oldContext);
329 
330  return entry;
331 }
unsigned int uint32
Definition: c.h:493
static uint32 TupleHashTableHash_internal(struct tuplehash_hash *tb, const MinimalTuple tuple)
Definition: execGrouping.c:425
static TupleHashEntry LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 hash)
Definition: execGrouping.c:495
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715

References Assert(), TupleHashTableData::cur_eq_func, hash(), TupleHashEntryData::hash, TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, LookupTupleHashEntry_internal(), MemoryContextSwitchTo(), TupleHashTableData::tab_eq_func, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tempcxt, and TupleHashTableHash_internal().

Referenced by buildSubPlanHash(), ExecRecursiveUnion(), lookup_hash_entries(), and setop_fill_hash_table().

◆ LookupTupleHashEntryHash()

TupleHashEntry LookupTupleHashEntryHash ( TupleHashTable  hashtable,
TupleTableSlot slot,
bool isnew,
uint32  hash 
)

Definition at line 360 of file execGrouping.c.

362 {
363  TupleHashEntry entry;
364  MemoryContext oldContext;
365 
366  /* Need to run the hash functions in short-lived context */
367  oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
368 
369  /* set up data needed by hash and match functions */
370  hashtable->inputslot = slot;
371  hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
372  hashtable->cur_eq_func = hashtable->tab_eq_func;
373 
374  entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, hash);
375  Assert(entry == NULL || entry->hash == hash);
376 
377  MemoryContextSwitchTo(oldContext);
378 
379  return entry;
380 }

References Assert(), TupleHashTableData::cur_eq_func, hash(), TupleHashEntryData::hash, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, LookupTupleHashEntry_internal(), MemoryContextSwitchTo(), TupleHashTableData::tab_eq_func, TupleHashTableData::tab_hash_funcs, and TupleHashTableData::tempcxt.

Referenced by agg_refill_hash_table().

◆ MakePerTupleExprContext()

ExprContext* MakePerTupleExprContext ( EState estate)

Definition at line 456 of file execUtils.c.

457 {
458  if (estate->es_per_tuple_exprcontext == NULL)
460 
461  return estate->es_per_tuple_exprcontext;
462 }

References CreateExprContext(), and EState::es_per_tuple_exprcontext.

◆ MultiExecProcNode()

Node* MultiExecProcNode ( PlanState node)

Definition at line 502 of file execProcnode.c.

503 {
504  Node *result;
505 
507 
509 
510  if (node->chgParam != NULL) /* something changed */
511  ExecReScan(node); /* let ReScan handle this */
512 
513  switch (nodeTag(node))
514  {
515  /*
516  * Only node types that actually support multiexec will be listed
517  */
518 
519  case T_HashState:
520  result = MultiExecHash((HashState *) node);
521  break;
522 
523  case T_BitmapIndexScanState:
525  break;
526 
527  case T_BitmapAndState:
528  result = MultiExecBitmapAnd((BitmapAndState *) node);
529  break;
530 
531  case T_BitmapOrState:
532  result = MultiExecBitmapOr((BitmapOrState *) node);
533  break;
534 
535  default:
536  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
537  result = NULL;
538  break;
539  }
540 
541  return result;
542 }
Node * MultiExecBitmapAnd(BitmapAndState *node)
Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node)
Node * MultiExecBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:111
Node * MultiExecHash(HashState *node)
Definition: nodeHash.c:105

References CHECK_FOR_INTERRUPTS, check_stack_depth(), PlanState::chgParam, elog, ERROR, ExecReScan(), MultiExecBitmapAnd(), MultiExecBitmapIndexScan(), MultiExecBitmapOr(), MultiExecHash(), and nodeTag.

Referenced by BitmapHeapNext(), ExecHashJoinImpl(), MultiExecBitmapAnd(), and MultiExecBitmapOr().

◆ RegisterExprContextCallback()

void RegisterExprContextCallback ( ExprContext econtext,
ExprContextCallbackFunction  function,
Datum  arg 
)

Definition at line 897 of file execUtils.c.

900 {
901  ExprContext_CB *ecxt_callback;
902 
903  /* Save the info in appropriate memory context */
904  ecxt_callback = (ExprContext_CB *)
906  sizeof(ExprContext_CB));
907 
908  ecxt_callback->function = function;
909  ecxt_callback->arg = arg;
910 
911  /* link to front of list for appropriate execution order */
912  ecxt_callback->next = econtext->ecxt_callbacks;
913  econtext->ecxt_callbacks = ecxt_callback;
914 }
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1168
void * arg
struct ExprContext_CB * next
Definition: execnodes.h:221
ExprContextCallbackFunction function
Definition: execnodes.h:222

References arg, ExprContext_CB::arg, ExprContext::ecxt_callbacks, ExprContext::ecxt_per_query_memory, ExprContext_CB::function, MemoryContextAlloc(), and ExprContext_CB::next.

Referenced by AggRegisterCallback(), ExecMakeFunctionResultSet(), ExecPrepareTuplestoreResult(), fmgr_sql(), and init_MultiFuncCall().

◆ RelationFindReplTupleByIndex()

bool RelationFindReplTupleByIndex ( Relation  rel,
Oid  idxoid,
LockTupleMode  lockmode,
TupleTableSlot searchslot,
TupleTableSlot outslot 
)

Definition at line 176 of file execReplication.c.

180 {
182  int skey_attoff;
183  IndexScanDesc scan;
184  SnapshotData snap;
185  TransactionId xwait;
186  Relation idxrel;
187  bool found;
188  TypeCacheEntry **eq = NULL;
189  bool isIdxSafeToSkipDuplicates;
190 
191  /* Open the index. */
192  idxrel = index_open(idxoid, RowExclusiveLock);
193 
194  isIdxSafeToSkipDuplicates = (GetRelationIdentityOrPK(rel) == idxoid);
195 
196  InitDirtySnapshot(snap);
197 
198  /* Build scan key. */
199  skey_attoff = build_replindex_scan_key(skey, rel, idxrel, searchslot);
200 
201  /* Start an index scan. */
202  scan = index_beginscan(rel, idxrel, &snap, skey_attoff, 0);
203 
204 retry:
205  found = false;
206 
207  index_rescan(scan, skey, skey_attoff, NULL, 0);
208 
209  /* Try to find the tuple */
210  while (index_getnext_slot(scan, ForwardScanDirection, outslot))
211  {
212  /*
213  * Avoid expensive equality check if the index is primary key or
214  * replica identity index.
215  */
216  if (!isIdxSafeToSkipDuplicates)
217  {
218  if (eq == NULL)
219  eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
220 
221  if (!tuples_equal(outslot, searchslot, eq))
222  continue;
223  }
224 
225  ExecMaterializeSlot(outslot);
226 
227  xwait = TransactionIdIsValid(snap.xmin) ?
228  snap.xmin : snap.xmax;
229 
230  /*
231  * If the tuple is locked, wait for locking transaction to finish and
232  * retry.
233  */
234  if (TransactionIdIsValid(xwait))
235  {
236  XactLockTableWait(xwait, NULL, NULL, XLTW_None);
237  goto retry;
238  }
239 
240  /* Found our tuple and it's not locked */
241  found = true;
242  break;
243  }
244 
245  /* Found tuple, try to lock it in the lockmode. */
246  if (found)
247  {
248  TM_FailureData tmfd;
249  TM_Result res;
250 
252 
253  res = table_tuple_lock(rel, &(outslot->tts_tid), GetLatestSnapshot(),
254  outslot,
255  GetCurrentCommandId(false),
256  lockmode,
258  0 /* don't follow updates */ ,
259  &tmfd);
260 
262 
263  switch (res)
264  {
265  case TM_Ok:
266  break;
267  case TM_Updated:
268  /* XXX: Improve handling here */
270  ereport(LOG,
272  errmsg("tuple to be locked was already moved to another partition due to concurrent update, retrying")));
273  else
274  ereport(LOG,
276  errmsg("concurrent update, retrying")));
277  goto retry;
278  case TM_Deleted:
279  /* XXX: Improve handling here */
280  ereport(LOG,
282  errmsg("concurrent delete, retrying")));
283  goto retry;
284  case TM_Invisible:
285  elog(ERROR, "attempted to lock invisible tuple");
286  break;
287  default:
288  elog(ERROR, "unexpected table_tuple_lock status: %u", res);
289  break;
290  }
291  }
292 
293  index_endscan(scan);
294 
295  /* Don't release lock until commit. */
296  index_close(idxrel, NoLock);
297 
298  return found;
299 }
uint32 TransactionId
Definition: c.h:639
#define LOG
Definition: elog.h:31
static bool tuples_equal(TupleTableSlot *slot1, TupleTableSlot *slot2, TypeCacheEntry **eq)
static int build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel, TupleTableSlot *searchslot)
bool index_getnext_slot(IndexScanDesc scan, ScanDirection direction, TupleTableSlot *slot)
Definition: indexam.c:676
IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, int norderbys)
Definition: indexam.c:257
void index_endscan(IndexScanDesc scan)
Definition: indexam.c:379
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:353
static bool ItemPointerIndicatesMovedPartitions(const ItemPointerData *pointer)
Definition: itemptr.h:197
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:667
@ XLTW_None
Definition: lmgr.h:26
@ LockWaitBlock
Definition: lockoptions.h:39
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition: pgbench.c:76
Snapshot GetLatestSnapshot(void)
Definition: snapmgr.c:291
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:648
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
#define InitDirtySnapshot(snapshotdata)
Definition: snapmgr.h:40
Oid GetRelationIdentityOrPK(Relation rel)
Definition: relation.c:851
TransactionId xmin
Definition: snapshot.h:157
TransactionId xmax
Definition: snapshot.h:158
ItemPointerData ctid
Definition: tableam.h:142
TM_Result
Definition: tableam.h:72
@ TM_Ok
Definition: tableam.h:77
@ TM_Deleted
Definition: tableam.h:92
@ TM_Updated
Definition: tableam.h:89
@ TM_Invisible
Definition: tableam.h:80
static TM_Result table_tuple_lock(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, uint8 flags, TM_FailureData *tmfd)
Definition: tableam.h:1570
#define TransactionIdIsValid(xid)
Definition: transam.h:41
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:819

References build_replindex_scan_key(), TM_FailureData::ctid, elog, ereport, errcode(), ERRCODE_T_R_SERIALIZATION_FAILURE, errmsg(), ERROR, ExecMaterializeSlot(), ForwardScanDirection, GetCurrentCommandId(), GetLatestSnapshot(), GetRelationIdentityOrPK(), index_beginscan(), index_close(), index_endscan(), index_getnext_slot(), INDEX_MAX_KEYS, index_open(), index_rescan(), InitDirtySnapshot, ItemPointerIndicatesMovedPartitions(), LockWaitBlock, LOG, TupleDescData::natts, NoLock, palloc0(), PopActiveSnapshot(), PushActiveSnapshot(), res, RowExclusiveLock, table_tuple_lock(), TM_Deleted, TM_Invisible, TM_Ok, TM_Updated, TransactionIdIsValid, TupleTableSlot::tts_tid, TupleTableSlot::tts_tupleDescriptor, tuples_equal(), XactLockTableWait(), XLTW_None, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by FindReplTupleInLocalRel().

◆ RelationFindReplTupleSeq()

bool RelationFindReplTupleSeq ( Relation  rel,
LockTupleMode  lockmode,
TupleTableSlot searchslot,
TupleTableSlot outslot 
)

Definition at line 378 of file execReplication.c.

380 {
381  TupleTableSlot *scanslot;
382  TableScanDesc scan;
383  SnapshotData snap;
384  TypeCacheEntry **eq;
385  TransactionId xwait;
386  bool found;
388 
389  Assert(equalTupleDescs(desc, outslot->tts_tupleDescriptor));
390 
391  eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
392 
393  /* Start a heap scan. */
394  InitDirtySnapshot(snap);
395  scan = table_beginscan(rel, &snap, 0, NULL);
396  scanslot = table_slot_create(rel, NULL);
397 
398 retry:
399  found = false;
400 
401  table_rescan(scan, NULL);
402 
403  /* Try to find the tuple */
404  while (table_scan_getnextslot(scan, ForwardScanDirection, scanslot))
405  {
406  if (!tuples_equal(scanslot, searchslot, eq))
407  continue;
408 
409  found = true;
410  ExecCopySlot(outslot, scanslot);
411 
412  xwait = TransactionIdIsValid(snap.xmin) ?
413  snap.xmin : snap.xmax;
414 
415  /*
416  * If the tuple is locked, wait for locking transaction to finish and
417  * retry.
418  */
419  if (TransactionIdIsValid(xwait))
420  {
421  XactLockTableWait(xwait, NULL, NULL, XLTW_None);
422  goto retry;
423  }
424 
425  /* Found our tuple and it's not locked */
426  break;
427  }
428 
429  /* Found tuple, try to lock it in the lockmode. */
430  if (found)
431  {
432  TM_FailureData tmfd;
433  TM_Result res;
434 
436 
437  res = table_tuple_lock(rel, &(outslot->tts_tid), GetLatestSnapshot(),
438  outslot,
439  GetCurrentCommandId(false),
440  lockmode,
442  0 /* don't follow updates */ ,
443  &tmfd);
444 
446 
447  switch (res)
448  {
449  case TM_Ok:
450  break;
451  case TM_Updated:
452  /* XXX: Improve handling here */
454  ereport(LOG,
456  errmsg("tuple to be locked was already moved to another partition due to concurrent update, retrying")));
457  else
458  ereport(LOG,
460  errmsg("concurrent update, retrying")));
461  goto retry;
462  case TM_Deleted:
463  /* XXX: Improve handling here */
464  ereport(LOG,
466  errmsg("concurrent delete, retrying")));
467  goto retry;
468  case TM_Invisible:
469  elog(ERROR, "attempted to lock invisible tuple");
470  break;
471  default:
472  elog(ERROR, "unexpected table_tuple_lock status: %u", res);
473  break;
474  }
475  }
476 
477  table_endscan(scan);
479 
480  return found;
481 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:169
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:901
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1009
static void table_rescan(TableScanDesc scan, struct ScanKeyData *key)
Definition: tableam.h:1018
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1045
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:419

References Assert(), TM_FailureData::ctid, elog, equalTupleDescs(), ereport, errcode(), ERRCODE_T_R_SERIALIZATION_FAILURE, errmsg(), ERROR, ExecCopySlot(), ExecDropSingleTupleTableSlot(), ForwardScanDirection, GetCurrentCommandId(), GetLatestSnapshot(), InitDirtySnapshot, ItemPointerIndicatesMovedPartitions(), LockWaitBlock, LOG, TupleDescData::natts, palloc0(), PG_USED_FOR_ASSERTS_ONLY, PopActiveSnapshot(), PushActiveSnapshot(), RelationGetDescr, res, table_beginscan(), table_endscan(), table_rescan(), table_scan_getnextslot(), table_slot_create(), table_tuple_lock(), TM_Deleted, TM_Invisible, TM_Ok, TM_Updated, TransactionIdIsValid, TupleTableSlot::tts_tid, TupleTableSlot::tts_tupleDescriptor, tuples_equal(), XactLockTableWait(), XLTW_None, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by FindReplTupleInLocalRel().

◆ ReScanExprContext()

void ReScanExprContext ( ExprContext econtext)

Definition at line 441 of file execUtils.c.

442 {
443  /* Call any registered callbacks */
444  ShutdownExprContext(econtext, true);
445  /* And clean up the memory used */
447 }

References ExprContext::ecxt_per_tuple_memory, MemoryContextReset(), and ShutdownExprContext().

Referenced by agg_refill_hash_table(), agg_retrieve_direct(), domain_check_input(), ExecEndAgg(), ExecReScan(), ExecReScanAgg(), and ValuesNext().

◆ ResetTupleHashTable()

void ResetTupleHashTable ( TupleHashTable  hashtable)

Definition at line 284 of file execGrouping.c.

285 {
286  tuplehash_reset(hashtable->hashtab);
287 }

References TupleHashTableData::hashtab.

Referenced by agg_refill_hash_table(), build_hash_tables(), buildSubPlanHash(), ExecReScanRecursiveUnion(), and ExecReScanSetOp().

◆ standard_ExecutorEnd()

void standard_ExecutorEnd ( QueryDesc queryDesc)

Definition at line 476 of file execMain.c.

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

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

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

◆ standard_ExecutorFinish()

void standard_ExecutorFinish ( QueryDesc queryDesc)

Definition at line 416 of file execMain.c.

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

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

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

◆ standard_ExecutorRun()

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

Definition at line 308 of file execMain.c.

310 {
311  EState *estate;
312  CmdType operation;
314  bool sendTuples;
315  MemoryContext oldcontext;
316 
317  /* sanity checks */
318  Assert(queryDesc != NULL);
319 
320  estate = queryDesc->estate;
321 
322  Assert(estate != NULL);
324 
325  /* caller must ensure the query's snapshot is active */
326  Assert(GetActiveSnapshot() == estate->es_snapshot);
327 
328  /*
329  * Switch into per-query memory context
330  */
331  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
332 
333  /* Allow instrumentation of Executor overall runtime */
334  if (queryDesc->totaltime)
335  InstrStartNode(queryDesc->totaltime);
336 
337  /*
338  * extract information from the query descriptor and the query feature.
339  */
340  operation = queryDesc->operation;
341  dest = queryDesc->dest;
342 
343  /*
344  * startup tuple receiver, if we will be emitting tuples
345  */
346  estate->es_processed = 0;
347 
348  sendTuples = (operation == CMD_SELECT ||
349  queryDesc->plannedstmt->hasReturning);
350 
351  if (sendTuples)
352  dest->rStartup(dest, operation, queryDesc->tupDesc);
353 
354  /*
355  * run plan
356  */
357  if (!ScanDirectionIsNoMovement(direction))
358  {
359  if (execute_once && queryDesc->already_executed)
360  elog(ERROR, "can't re-execute query flagged for single execution");
361  queryDesc->already_executed = true;
362 
363  ExecutePlan(estate,
364  queryDesc->planstate,
365  queryDesc->plannedstmt->parallelModeNeeded,
366  operation,
367  sendTuples,
368  count,
369  direction,
370  dest,
371  execute_once);
372  }
373 
374  /*
375  * Update es_total_processed to keep track of the number of tuples
376  * processed across multiple ExecutorRun() calls.
377  */
378  estate->es_total_processed += estate->es_processed;
379 
380  /*
381  * shutdown tuple receiver, if we started it
382  */
383  if (sendTuples)
384  dest->rShutdown(dest);
385 
386  if (queryDesc->totaltime)
387  InstrStopNode(queryDesc->totaltime, estate->es_processed);
388 
389  MemoryContextSwitchTo(oldcontext);
390 }
static void ExecutePlan(EState *estate, PlanState *planstate, bool use_parallel_mode, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, DestReceiver *dest, bool execute_once)
Definition: execMain.c:1599
CmdType
Definition: nodes.h:253
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:57
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:770
bool hasReturning
Definition: plannodes.h:56
bool parallelModeNeeded
Definition: plannodes.h:66
DestReceiver * dest
Definition: execdesc.h:41
bool already_executed
Definition: execdesc.h:52

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

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

◆ standard_ExecutorStart()

void standard_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 141 of file execMain.c.

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

References AfterTriggerBeginQuery(), Assert(), CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_SELECT, CMD_UPDATE, CreateExecutorState(), QueryDesc::crosscheck_snapshot, elog, ERROR, EState::es_crosscheck_snapshot, EState::es_instrument, EState::es_jit_flags, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_query_cxt, EState::es_queryEnv, EState::es_snapshot, EState::es_sourceText, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_SKIP_TRIGGERS, ExecCheckXactReadOnly(), GetActiveSnapshot(), GetCurrentCommandId(), PlannedStmt::hasModifyingCTE, InitPlan(), QueryDesc::instrument_options, IsInParallelMode(), PlannedStmt::jitFlags, list_length(), MemoryContextSwitchTo(), NIL, QueryDesc::operation, palloc0(), PlannedStmt::paramExecTypes, QueryDesc::params, QueryDesc::plannedstmt, QueryDesc::queryEnv, RegisterSnapshot(), PlannedStmt::rowMarks, QueryDesc::snapshot, QueryDesc::sourceText, and XactReadOnly.

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

◆ TupleHashTableHash()

uint32 TupleHashTableHash ( TupleHashTable  hashtable,
TupleTableSlot slot 
)

Definition at line 337 of file execGrouping.c.

338 {
339  MemoryContext oldContext;
340  uint32 hash;
341 
342  hashtable->inputslot = slot;
343  hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
344 
345  /* Need to run the hash functions in short-lived context */
346  oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
347 
348  hash = TupleHashTableHash_internal(hashtable->hashtab, NULL);
349 
350  MemoryContextSwitchTo(oldContext);
351 
352  return hash;
353 }

References hash(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, MemoryContextSwitchTo(), TupleHashTableData::tab_hash_funcs, TupleHashTableData::tempcxt, and TupleHashTableHash_internal().

◆ UnregisterExprContextCallback()

void UnregisterExprContextCallback ( ExprContext econtext,
ExprContextCallbackFunction  function,
Datum  arg 
)

Definition at line 923 of file execUtils.c.

926 {
927  ExprContext_CB **prev_callback;
928  ExprContext_CB *ecxt_callback;
929 
930  prev_callback = &econtext->ecxt_callbacks;
931 
932  while ((ecxt_callback = *prev_callback) != NULL)
933  {
934  if (ecxt_callback->function == function && ecxt_callback->arg == arg)
935  {
936  *prev_callback = ecxt_callback->next;
937  pfree(ecxt_callback);
938  }
939  else
940  prev_callback = &ecxt_callback->next;
941  }
942 }

References arg, ExprContext_CB::arg, ExprContext::ecxt_callbacks, ExprContext_CB::function, ExprContext_CB::next, and pfree().

Referenced by end_MultiFuncCall(), and fmgr_sql().

◆ UpdateChangedParamSet()

void UpdateChangedParamSet ( PlanState node,
Bitmapset newchg 
)

Definition at line 844 of file execUtils.c.

845 {
846  Bitmapset *parmset;
847 
848  /*
849  * The plan node only depends on params listed in its allParam set. Don't
850  * include anything else into its chgParam set.
851  */
852  parmset = bms_intersect(node->plan->allParam, newchg);
853  node->chgParam = bms_join(node->chgParam, parmset);
854 }
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:1230
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:292
Bitmapset * allParam
Definition: plannodes.h:171

References Plan::allParam, bms_intersect(), bms_join(), PlanState::chgParam, and PlanState::plan.

Referenced by ExecReScan(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapOr(), ExecReScanMergeAppend(), and ExecReScanSubqueryScan().

Variable Documentation

◆ ExecutorCheckPerms_hook

PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
extern

Definition at line 71 of file execMain.c.

Referenced by _PG_init(), and ExecCheckPermissions().

◆ ExecutorEnd_hook

PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook
extern

Definition at line 68 of file execMain.c.

Referenced by _PG_init(), and ExecutorEnd().

◆ ExecutorFinish_hook

PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook
extern

Definition at line 67 of file execMain.c.

Referenced by _PG_init(), and ExecutorFinish().

◆ ExecutorRun_hook

PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook
extern

Definition at line 66 of file execMain.c.

Referenced by _PG_init(), and ExecutorRun().

◆ ExecutorStart_hook

PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook
extern

Definition at line 65 of file execMain.c.

Referenced by _PG_init(), and ExecutorStart().