PostgreSQL Source Code git master
Loading...
Searching...
No Matches
executor.h File Reference
#include "datatype/timestamp.h"
#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)
 
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 struct Path Path
 
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 (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, const TupleTableSlotOps *inputOps, int numCols, AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, double nelements, Size additionalsize, MemoryContext metacxt, MemoryContext tuplescxt, 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, ExprState *hashexpr)
 
void ResetTupleHashTable (TupleHashTable hashtable)
 
Size EstimateTupleHashTableSpace (double nentries, Size tupleWidth, Size additionalsize)
 
static size_t TupleHashEntrySize (void)
 
static MinimalTuple TupleHashEntryGetTuple (TupleHashEntry entry)
 
static voidTupleHashEntryGetAdditional (TupleHashTable hashtable, TupleHashEntry entry)
 
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)
 
void standard_ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, uint64 count)
 
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)
 
bool ExecCheckOneRelPerms (RTEPermissionInfo *perminfo)
 
void CheckValidResultRel (ResultRelInfo *resultRelInfo, CmdType operation, OnConflictAction onConflictAction, 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)
 
AttrNumber ExecRelGenVirtualNotNull (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, List *notnull_virtual_attrs)
 
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)
 
charExecBuildSlotValueDescription (Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
 
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)
 
ExprStateExecBuildHash32FromAttrs (TupleDesc desc, const TupleTableSlotOps *ops, FmgrInfo *hashfunctions, Oid *collations, int numCols, AttrNumber *keyColIdx, PlanState *parent, uint32 init_value)
 
ExprStateExecBuildHash32Expr (TupleDesc desc, const TupleTableSlotOps *ops, const Oid *hashfunc_oids, const List *collations, const List *hash_exprs, const bool *opstrict, PlanState *parent, uint32 init_value, bool keep_nulls)
 
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 void ExecEvalExprNoReturn (ExprState *state, ExprContext *econtext)
 
static Datum ExecEvalExprSwitchContext (ExprState *state, ExprContext *econtext, bool *isNull)
 
static void ExecEvalExprNoReturnSwitchContext (ExprState *state, ExprContext *econtext)
 
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)
 
const TupleTableSlotOpsExecGetCommonSlotOps (PlanState **planstates, int nplans)
 
const TupleTableSlotOpsExecGetCommonChildSlotOps (PlanState *ps)
 
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, Bitmapset *unpruned_relids)
 
void ExecCloseRangeTableRelations (EState *estate)
 
void ExecCloseResultRelations (EState *estate)
 
static RangeTblEntryexec_rt_fetch (Index rti, EState *estate)
 
Relation ExecGetRangeTableRelation (EState *estate, Index rti, bool isResultRel)
 
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)
 
TupleTableSlotExecGetAllNullSlot (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, const ItemPointerData *tupleid, List *arbiterIndexes)
 
void check_exclusion_constraint (Relation heap, Relation index, IndexInfo *indexInfo, const ItemPointerData *tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex)
 
bool RelationFindReplTupleByIndex (Relation rel, Oid idxoid, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
bool RelationFindReplTupleSeq (Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
bool RelationFindDeletedTupleInfoSeq (Relation rel, TupleTableSlot *searchslot, TransactionId oldestxmin, TransactionId *delete_xid, ReplOriginId *delete_origin, TimestampTz *delete_time)
 
bool RelationFindDeletedTupleInfoByIndex (Relation rel, Oid idxoid, TupleTableSlot *searchslot, TransactionId oldestxmin, TransactionId *delete_xid, ReplOriginId *delete_origin, TimestampTz *delete_time)
 
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 localrelkind, char remoterelkind, 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]; \
isnull_[0] = false; \
} while (0)
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
static int fb(int x)
text * cstring_to_text(const char *s)
Definition varlena.c:181

Definition at line 628 of file executor.h.

629 { \
630 Datum values_[1]; \
631 bool isnull_[1]; \
633 isnull_[0] = false; \
636 } while (0)

◆ EvalPlanQualSetSlot

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

Definition at line 289 of file executor.h.

◆ EXEC_FLAG_BACKWARD

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

Definition at line 69 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_GENERIC

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

Definition at line 67 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_ONLY

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

Definition at line 66 of file executor.h.

◆ EXEC_FLAG_MARK

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

Definition at line 70 of file executor.h.

◆ EXEC_FLAG_REWIND

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

Definition at line 68 of file executor.h.

◆ EXEC_FLAG_SKIP_TRIGGERS

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

Definition at line 71 of file executor.h.

◆ EXEC_FLAG_WITH_NO_DATA

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

Definition at line 72 of file executor.h.

◆ GetPerTupleExprContext

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

Definition at line 656 of file executor.h.

658 : \

◆ GetPerTupleMemoryContext

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

Definition at line 661 of file executor.h.

◆ ResetExprContext

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

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

666 { \
667 if ((estate)->es_per_tuple_exprcontext) \
668 ResetExprContext((estate)->es_per_tuple_exprcontext); \
669 } while (0)

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 579 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 580 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)

Definition at line 80 of file executor.h.

◆ ExecutorStart_hook_type

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

Definition at line 76 of file executor.h.

◆ Path

Definition at line 103 of file executor.h.

◆ TupOutputState

Function Documentation

◆ begin_tup_output_tupdesc()

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

Definition at line 2444 of file execTuples.c.

2447{
2449
2451
2452 tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2453 tstate->dest = dest;
2454
2455 tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2456
2457 return tstate;
2458}
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
#define palloc_object(type)
Definition fe_memutils.h:74
@ CMD_SELECT
Definition nodes.h:275

References CMD_SELECT, fb(), MakeSingleTupleTableSlot(), and palloc_object.

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

◆ BuildTupleHashTable()

TupleHashTable BuildTupleHashTable ( PlanState parent,
TupleDesc  inputDesc,
const TupleTableSlotOps inputOps,
int  numCols,
AttrNumber keyColIdx,
const Oid eqfuncoids,
FmgrInfo hashfunctions,
Oid collations,
double  nelements,
Size  additionalsize,
MemoryContext  metacxt,
MemoryContext  tuplescxt,
MemoryContext  tempcxt,
bool  use_variable_hash_iv 
)
extern

Definition at line 184 of file execGrouping.c.

198{
199 TupleHashTable hashtable;
200 uint32 nbuckets;
201 MemoryContext oldcontext;
202 uint32 hash_iv = 0;
203
204 /*
205 * tuplehash_create requires a uint32 element count, so we had better
206 * clamp the given nelements to fit in that. As long as we have to do
207 * that, we might as well protect against completely insane input like
208 * zero or NaN. But it is not our job here to enforce issues like staying
209 * within hash_mem: the caller should have done that, and we don't have
210 * enough info to second-guess.
211 */
212 if (isnan(nelements) || nelements <= 0)
213 nbuckets = 1;
214 else if (nelements >= PG_UINT32_MAX)
215 nbuckets = PG_UINT32_MAX;
216 else
217 nbuckets = (uint32) nelements;
218
219 /* tuplescxt must be separate, else ResetTupleHashTable breaks things */
220 Assert(metacxt != tuplescxt);
221
222 /* ensure additionalsize is maxalign'ed */
223 additionalsize = MAXALIGN(additionalsize);
224
225 oldcontext = MemoryContextSwitchTo(metacxt);
226
228
229 hashtable->numCols = numCols;
230 hashtable->keyColIdx = keyColIdx;
231 hashtable->tab_collations = collations;
232 hashtable->tuplescxt = tuplescxt;
233 hashtable->tempcxt = tempcxt;
234 hashtable->additionalsize = additionalsize;
235 hashtable->tableslot = NULL; /* will be made on first lookup */
236 hashtable->inputslot = NULL;
237 hashtable->in_hash_expr = NULL;
238 hashtable->cur_eq_func = NULL;
239
240 /*
241 * If parallelism is in use, even if the leader backend is performing the
242 * scan itself, we don't want to create the hashtable exactly the same way
243 * in all workers. As hashtables are iterated over in keyspace-order,
244 * doing so in all processes in the same way is likely to lead to
245 * "unbalanced" hashtables when the table size initially is
246 * underestimated.
247 */
250
251 hashtable->hashtab = tuplehash_create(metacxt, nbuckets, hashtable);
252
253 /*
254 * We copy the input tuple descriptor just for safety --- we assume all
255 * input tuples will have equivalent descriptors.
256 */
259
260 /* build hash ExprState for all columns */
262 inputOps,
263 hashfunctions,
264 collations,
265 numCols,
266 keyColIdx,
267 parent,
268 hash_iv);
269
270 /* build comparator for all columns */
272 inputOps,
274 numCols,
275 keyColIdx, eqfuncoids, collations,
276 parent);
277
278 /*
279 * While not pretty, it's ok to not shut down this context, but instead
280 * rely on the containing memory context being reset, as
281 * ExecBuildGroupingEqual() only builds a very simple expression calling
282 * functions (i.e. nothing that'd employ RegisterExprContextCallback()).
283 */
285
286 MemoryContextSwitchTo(oldcontext);
287
288 return hashtable;
289}
int ParallelWorkerNumber
Definition parallel.c:115
#define MAXALIGN(LEN)
Definition c.h:826
#define PG_UINT32_MAX
Definition c.h:604
#define Assert(condition)
Definition c.h:873
uint32_t uint32
Definition c.h:546
ExprState * ExecBuildHash32FromAttrs(TupleDesc desc, const TupleTableSlotOps *ops, FmgrInfo *hashfunctions, Oid *collations, int numCols, AttrNumber *keyColIdx, PlanState *parent, uint32 init_value)
Definition execExpr.c:4135
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:4459
const TupleTableSlotOps TTSOpsMinimalTuple
Definition execTuples.c:86
ExprContext * CreateStandaloneExprContext(void)
Definition execUtils.c:357
static uint32 murmurhash32(uint32 data)
Definition hashfn.h:92
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
AttrNumber * keyColIdx
Definition execnodes.h:874
tuplehash_hash * hashtab
Definition execnodes.h:872
ExprState * in_hash_expr
Definition execnodes.h:884
ExprState * tab_hash_expr
Definition execnodes.h:875
MemoryContext tempcxt
Definition execnodes.h:879
ExprState * tab_eq_func
Definition execnodes.h:876
TupleTableSlot * tableslot
Definition execnodes.h:881
ExprContext * exprcontext
Definition execnodes.h:886
TupleTableSlot * inputslot
Definition execnodes.h:883
ExprState * cur_eq_func
Definition execnodes.h:885
MemoryContext tuplescxt
Definition execnodes.h:878
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:252

References TupleHashTableData::additionalsize, Assert, CreateStandaloneExprContext(), CreateTupleDescCopy(), TupleHashTableData::cur_eq_func, ExecBuildGroupingEqual(), ExecBuildHash32FromAttrs(), TupleHashTableData::exprcontext, fb(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_expr, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, MakeSingleTupleTableSlot(), MAXALIGN, MemoryContextSwitchTo(), murmurhash32(), TupleHashTableData::numCols, palloc_object, ParallelWorkerNumber, PG_UINT32_MAX, TupleHashTableData::tab_collations, TupleHashTableData::tab_eq_func, TupleHashTableData::tab_hash_expr, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, TTSOpsMinimalTuple, and TupleHashTableData::tuplescxt.

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

◆ check_exclusion_constraint()

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

Definition at line 962 of file execIndexing.c.

967{
969 values, isnull,
970 estate, newIndex,
971 CEOUC_WAIT, false, NULL);
972}
static Datum values[MAXATTR]
Definition bootstrap.c:155
@ CEOUC_WAIT
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, const ItemPointerData *tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool violationOK, ItemPointer conflictTid)
Definition type.h:96

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), fb(), and values.

Referenced by IndexCheckExclusion(), and unique_key_recheck().

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)
extern

Definition at line 1011 of file execReplication.c.

1012{
1014
1015 /*
1016 * Skip checking the replica identity for partitioned tables, because the
1017 * operations are actually performed on the leaf partitions.
1018 */
1019 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1020 return;
1021
1022 /* We only need to do checks for UPDATE and DELETE. */
1023 if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
1024 return;
1025
1026 /*
1027 * It is only safe to execute UPDATE/DELETE if the relation does not
1028 * publish UPDATEs or DELETEs, or all the following conditions are
1029 * satisfied:
1030 *
1031 * 1. All columns, referenced in the row filters from publications which
1032 * the relation is in, are valid - i.e. when all referenced columns are
1033 * part of REPLICA IDENTITY.
1034 *
1035 * 2. All columns, referenced in the column lists are valid - i.e. when
1036 * all columns referenced in the REPLICA IDENTITY are covered by the
1037 * column list.
1038 *
1039 * 3. All generated columns in REPLICA IDENTITY of the relation, are valid
1040 * - i.e. when all these generated columns are published.
1041 *
1042 * XXX We could optimize it by first checking whether any of the
1043 * publications have a row filter or column list for this relation, or if
1044 * the relation contains a generated column. If none of these exist and
1045 * the relation has replica identity then we can avoid building the
1046 * descriptor but as this happens only one time it doesn't seem worth the
1047 * additional complexity.
1048 */
1050 if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
1051 ereport(ERROR,
1053 errmsg("cannot update table \"%s\"",
1055 errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
1056 else if (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
1057 ereport(ERROR,
1059 errmsg("cannot update table \"%s\"",
1061 errdetail("Column list used by the publication does not cover the replica identity.")));
1062 else if (cmd == CMD_UPDATE && !pubdesc.gencols_valid_for_update)
1063 ereport(ERROR,
1065 errmsg("cannot update table \"%s\"",
1067 errdetail("Replica identity must not contain unpublished generated columns.")));
1068 else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
1069 ereport(ERROR,
1071 errmsg("cannot delete from table \"%s\"",
1073 errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
1074 else if (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
1075 ereport(ERROR,
1077 errmsg("cannot delete from table \"%s\"",
1079 errdetail("Column list used by the publication does not cover the replica identity.")));
1080 else if (cmd == CMD_DELETE && !pubdesc.gencols_valid_for_delete)
1081 ereport(ERROR,
1083 errmsg("cannot delete from table \"%s\"",
1085 errdetail("Replica identity must not contain unpublished generated columns.")));
1086
1087 /* If relation has replica identity we are always good. */
1089 return;
1090
1091 /* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */
1092 if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
1093 return;
1094
1095 /*
1096 * This is UPDATE/DELETE and there is no replica identity.
1097 *
1098 * Check if the table publishes UPDATES or DELETES.
1099 */
1100 if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
1101 ereport(ERROR,
1103 errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
1105 errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
1106 else if (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
1107 ereport(ERROR,
1109 errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
1111 errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
1112}
#define OidIsValid(objectId)
Definition c.h:788
int errdetail(const char *fmt,...)
Definition elog.c:1216
int errhint(const char *fmt,...)
Definition elog.c:1330
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
@ CMD_DELETE
Definition nodes.h:278
@ CMD_UPDATE
Definition nodes.h:276
#define RelationGetRelationName(relation)
Definition rel.h:548
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Definition relcache.c:5789
Oid RelationGetReplicaIndex(Relation relation)
Definition relcache.c:5067
Form_pg_class rd_rel
Definition rel.h:111

References CMD_DELETE, CMD_UPDATE, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, fb(), OidIsValid, RelationData::rd_rel, RelationBuildPublicationDesc(), RelationGetRelationName, and RelationGetReplicaIndex().

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

◆ CheckSubscriptionRelkind()

void CheckSubscriptionRelkind ( char  localrelkind,
char  remoterelkind,
const char nspname,
const char relname 
)
extern

Definition at line 1122 of file execReplication.c.

1124{
1128 ereport(ERROR,
1130 errmsg("cannot use relation \"%s.%s\" as logical replication target",
1131 nspname, relname),
1133
1134 /*
1135 * Allow RELKIND_RELATION and RELKIND_PARTITIONED_TABLE to be treated
1136 * interchangeably, but ensure that sequences (RELKIND_SEQUENCE) match
1137 * exactly on both publisher and subscriber.
1138 */
1141 ereport(ERROR,
1143 /* translator: 3rd and 4th %s are "sequence" or "table" */
1144 errmsg("relation \"%s.%s\" type mismatch: source \"%s\", target \"%s\"",
1145 nspname, relname,
1146 remoterelkind == RELKIND_SEQUENCE ? "sequence" : "table",
1147 localrelkind == RELKIND_SEQUENCE ? "sequence" : "table"));
1148}
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, fb(), and relname.

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

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation,
OnConflictAction  onConflictAction,
List mergeActions 
)
extern

Definition at line 1054 of file execMain.c.

1056{
1057 Relation resultRel = resultRelInfo->ri_RelationDesc;
1058 FdwRoutine *fdwroutine;
1059
1060 /* Expect a fully-formed ResultRelInfo from InitResultRelInfo(). */
1061 Assert(resultRelInfo->ri_needLockTagTuple ==
1062 IsInplaceUpdateRelation(resultRel));
1063
1064 switch (resultRel->rd_rel->relkind)
1065 {
1066 case RELKIND_RELATION:
1068
1069 /*
1070 * For MERGE, check that the target relation supports each action.
1071 * For other operations, just check the operation itself.
1072 */
1073 if (operation == CMD_MERGE)
1075 CheckCmdReplicaIdentity(resultRel, action->commandType);
1076 else
1077 CheckCmdReplicaIdentity(resultRel, operation);
1078
1079 /*
1080 * For INSERT ON CONFLICT DO UPDATE, additionally check that the
1081 * target relation supports UPDATE.
1082 */
1083 if (onConflictAction == ONCONFLICT_UPDATE)
1085 break;
1086 case RELKIND_SEQUENCE:
1087 ereport(ERROR,
1089 errmsg("cannot change sequence \"%s\"",
1090 RelationGetRelationName(resultRel))));
1091 break;
1092 case RELKIND_TOASTVALUE:
1093 ereport(ERROR,
1095 errmsg("cannot change TOAST relation \"%s\"",
1096 RelationGetRelationName(resultRel))));
1097 break;
1098 case RELKIND_VIEW:
1099
1100 /*
1101 * Okay only if there's a suitable INSTEAD OF trigger. Otherwise,
1102 * complain, but omit errdetail because we haven't got the
1103 * information handy (and given that it really shouldn't happen,
1104 * it's not worth great exertion to get).
1105 */
1106 if (!view_has_instead_trigger(resultRel, operation, mergeActions))
1107 error_view_not_updatable(resultRel, operation, mergeActions,
1108 NULL);
1109 break;
1110 case RELKIND_MATVIEW:
1112 ereport(ERROR,
1114 errmsg("cannot change materialized view \"%s\"",
1115 RelationGetRelationName(resultRel))));
1116 break;
1118 /* Okay only if the FDW supports it */
1119 fdwroutine = resultRelInfo->ri_FdwRoutine;
1120 switch (operation)
1121 {
1122 case CMD_INSERT:
1123 if (fdwroutine->ExecForeignInsert == NULL)
1124 ereport(ERROR,
1126 errmsg("cannot insert into foreign table \"%s\"",
1127 RelationGetRelationName(resultRel))));
1128 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1129 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1130 ereport(ERROR,
1132 errmsg("foreign table \"%s\" does not allow inserts",
1133 RelationGetRelationName(resultRel))));
1134 break;
1135 case CMD_UPDATE:
1136 if (fdwroutine->ExecForeignUpdate == NULL)
1137 ereport(ERROR,
1139 errmsg("cannot update foreign table \"%s\"",
1140 RelationGetRelationName(resultRel))));
1141 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1142 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1143 ereport(ERROR,
1145 errmsg("foreign table \"%s\" does not allow updates",
1146 RelationGetRelationName(resultRel))));
1147 break;
1148 case CMD_DELETE:
1149 if (fdwroutine->ExecForeignDelete == NULL)
1150 ereport(ERROR,
1152 errmsg("cannot delete from foreign table \"%s\"",
1153 RelationGetRelationName(resultRel))));
1154 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1155 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1156 ereport(ERROR,
1158 errmsg("foreign table \"%s\" does not allow deletes",
1159 RelationGetRelationName(resultRel))));
1160 break;
1161 default:
1162 elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1163 break;
1164 }
1165 break;
1166 default:
1167 ereport(ERROR,
1169 errmsg("cannot change relation \"%s\"",
1170 RelationGetRelationName(resultRel))));
1171 break;
1172 }
1173}
bool IsInplaceUpdateRelation(Relation relation)
Definition catalog.c:183
#define elog(elevel,...)
Definition elog.h:226
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition matview.c:952
@ ONCONFLICT_UPDATE
Definition nodes.h:430
@ CMD_MERGE
Definition nodes.h:279
@ CMD_INSERT
Definition nodes.h:277
#define foreach_node(type, var, lst)
Definition pg_list.h:496
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
bool ri_needLockTagTuple
Definition execnodes.h:514
Relation ri_RelationDesc
Definition execnodes.h:482
struct FdwRoutine * ri_FdwRoutine
Definition execnodes.h:535

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

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

◆ CreateExecutorState()

EState * CreateExecutorState ( void  )
extern

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 estate->es_part_prune_infos = NIL;
122
123 estate->es_junkFilter = NULL;
124
125 estate->es_output_cid = (CommandId) 0;
126
127 estate->es_result_relations = NULL;
131
134
135 estate->es_param_list_info = NULL;
136 estate->es_param_exec_vals = NULL;
137
138 estate->es_queryEnv = NULL;
139
140 estate->es_query_cxt = qcontext;
141
142 estate->es_tupleTable = NIL;
143
144 estate->es_processed = 0;
145 estate->es_total_processed = 0;
146
147 estate->es_top_eflags = 0;
148 estate->es_instrument = 0;
149 estate->es_finished = false;
150
151 estate->es_exprcontexts = NIL;
152
153 estate->es_subplanstates = NIL;
154
155 estate->es_auxmodifytables = NIL;
156
158
159 estate->es_sourceText = NULL;
160
161 estate->es_use_parallel_mode = false;
164
165 estate->es_jit_flags = 0;
166 estate->es_jit = NULL;
167
168 /*
169 * Return the executor state structure
170 */
171 MemoryContextSwitchTo(oldcontext);
172
173 return estate;
174}
uint32 CommandId
Definition c.h:680
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define makeNode(_type_)
Definition nodes.h:161
#define NIL
Definition pg_list.h:68
@ ForwardScanDirection
Definition sdir.h:28
#define InvalidSnapshot
Definition snapshot.h:119
uint64 es_processed
Definition execnodes.h:716
List * es_part_prune_infos
Definition execnodes.h:672
int es_parallel_workers_to_launch
Definition execnodes.h:748
List * es_tuple_routing_result_relations
Definition execnodes.h:700
int es_top_eflags
Definition execnodes.h:721
struct JitContext * es_jit
Definition execnodes.h:766
int es_instrument
Definition execnodes.h:722
PlannedStmt * es_plannedstmt
Definition execnodes.h:671
QueryEnvironment * es_queryEnv
Definition execnodes.h:709
ResultRelInfo ** es_result_relations
Definition execnodes.h:687
ParamExecData * es_param_exec_vals
Definition execnodes.h:707
uint64 es_total_processed
Definition execnodes.h:718
List * es_range_table
Definition execnodes.h:664
List * es_rteperminfos
Definition execnodes.h:670
List * es_exprcontexts
Definition execnodes.h:725
ParamListInfo es_param_list_info
Definition execnodes.h:706
ExecRowMark ** es_rowmarks
Definition execnodes.h:668
bool es_finished
Definition execnodes.h:723
List * es_insert_pending_result_relations
Definition execnodes.h:773
MemoryContext es_query_cxt
Definition execnodes.h:712
List * es_tupleTable
Definition execnodes.h:714
ScanDirection es_direction
Definition execnodes.h:661
List * es_trig_target_relations
Definition execnodes.h:703
int es_jit_flags
Definition execnodes.h:765
List * es_opened_result_relations
Definition execnodes.h:690
bool es_use_parallel_mode
Definition execnodes.h:746
Relation * es_relations
Definition execnodes.h:666
List * es_subplanstates
Definition execnodes.h:727
ExprContext * es_per_tuple_exprcontext
Definition execnodes.h:736
int es_parallel_workers_launched
Definition execnodes.h:750
CommandId es_output_cid
Definition execnodes.h:684
Index es_range_table_size
Definition execnodes.h:665
List * es_insert_pending_modifytables
Definition execnodes.h:774
const char * es_sourceText
Definition execnodes.h:679
Snapshot es_snapshot
Definition execnodes.h:662
List * es_auxmodifytables
Definition execnodes.h:729
JunkFilter * es_junkFilter
Definition execnodes.h:681
Snapshot es_crosscheck_snapshot
Definition execnodes.h:663

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_parallel_workers_launched, EState::es_parallel_workers_to_launch, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_part_prune_infos, 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, fb(), ForwardScanDirection, InvalidSnapshot, makeNode, MemoryContextSwitchTo(), and NIL.

Referenced by afterTriggerInvokeEvents(), ATExecAddColumn(), 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(), MergePartitionsMoveRows(), operator_predicate_proof(), plpgsql_create_econtext(), plpgsql_inline_handler(), SplitPartitionMoveRows(), standard_ExecutorStart(), tuplesort_begin_cluster(), unique_key_recheck(), and validateDomainCheckConstraint().

◆ CreateExprContext()

ExprContext * CreateExprContext ( EState estate)
extern

Definition at line 307 of file execUtils.c.

308{
310}
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition execUtils.c:237

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext * CreateStandaloneExprContext ( void  )
extern

Definition at line 357 of file execUtils.c.

358{
359 ExprContext *econtext;
360
361 /* Create the ExprContext node within the caller's memory context */
362 econtext = makeNode(ExprContext);
363
364 /* Initialize fields of ExprContext */
365 econtext->ecxt_scantuple = NULL;
366 econtext->ecxt_innertuple = NULL;
367 econtext->ecxt_outertuple = NULL;
368
370
371 /*
372 * Create working memory for expression evaluation in this context.
373 */
374 econtext->ecxt_per_tuple_memory =
376 "ExprContext",
378
379 econtext->ecxt_param_exec_vals = NULL;
380 econtext->ecxt_param_list_info = NULL;
381
382 econtext->ecxt_aggvalues = NULL;
383 econtext->ecxt_aggnulls = NULL;
384
385 econtext->caseValue_datum = (Datum) 0;
386 econtext->caseValue_isNull = true;
387
388 econtext->domainValue_datum = (Datum) 0;
389 econtext->domainValue_isNull = true;
390
391 econtext->ecxt_estate = NULL;
392
393 econtext->ecxt_callbacks = NULL;
394
395 return econtext;
396}
Datum domainValue_datum
Definition execnodes.h:306
ParamListInfo ecxt_param_list_info
Definition execnodes.h:287
MemoryContext ecxt_per_tuple_memory
Definition execnodes.h:283
TupleTableSlot * ecxt_innertuple
Definition execnodes.h:277
ParamExecData * ecxt_param_exec_vals
Definition execnodes.h:286
Datum * ecxt_aggvalues
Definition execnodes.h:294
bool caseValue_isNull
Definition execnodes.h:302
TupleTableSlot * ecxt_scantuple
Definition execnodes.h:275
Datum caseValue_datum
Definition execnodes.h:300
bool * ecxt_aggnulls
Definition execnodes.h:296
MemoryContext ecxt_per_query_memory
Definition execnodes.h:282
ExprContext_CB * ecxt_callbacks
Definition execnodes.h:320
bool domainValue_isNull
Definition execnodes.h:308
struct EState * ecxt_estate
Definition execnodes.h:317
TupleTableSlot * ecxt_outertuple
Definition execnodes.h:279

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, fb(), and makeNode.

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

◆ CreateWorkExprContext()

ExprContext * CreateWorkExprContext ( EState estate)
extern

Definition at line 322 of file execUtils.c.

323{
324 Size maxBlockSize;
325
326 maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
327
328 /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
329 maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
330
331 /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
332 maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
333
335 ALLOCSET_DEFAULT_INITSIZE, maxBlockSize);
336}
#define Min(x, y)
Definition c.h:997
#define Max(x, y)
Definition c.h:991
size_t Size
Definition c.h:619
int work_mem
Definition globals.c:131
#define ALLOCSET_DEFAULT_MAXSIZE
Definition memutils.h:159
#define ALLOCSET_DEFAULT_MINSIZE
Definition memutils.h:157
#define ALLOCSET_DEFAULT_INITSIZE
Definition memutils.h:158
#define pg_prevpower2_size_t

References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, CreateExprContextInternal(), Max, Min, pg_prevpower2_size_t, and work_mem.

Referenced by hash_create_memory().

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char txt 
)
extern

Definition at line 2492 of file execTuples.c.

2493{
2494 Datum values[1];
2495 bool isnull[1] = {false};
2496
2497 while (*txt)
2498 {
2499 const char *eol;
2500 int len;
2501
2502 eol = strchr(txt, '\n');
2503 if (eol)
2504 {
2505 len = eol - txt;
2506 eol++;
2507 }
2508 else
2509 {
2510 len = strlen(txt);
2511 eol = txt + len;
2512 }
2513
2515 do_tup_output(tstate, values, isnull);
2517 txt = eol;
2518 }
2519}
void do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
void pfree(void *pointer)
Definition mcxt.c:1616
const void size_t len
text * cstring_to_text_with_len(const char *s, int len)
Definition varlena.c:193

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

Referenced by ExplainQuery().

◆ do_tup_output()

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

Definition at line 2464 of file execTuples.c.

2465{
2466 TupleTableSlot *slot = tstate->slot;
2467 int natts = slot->tts_tupleDescriptor->natts;
2468
2469 /* make sure the slot is clear */
2470 ExecClearTuple(slot);
2471
2472 /* insert data */
2473 memcpy(slot->tts_values, values, natts * sizeof(Datum));
2474 memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2475
2476 /* mark slot as containing a virtual tuple */
2478
2479 /* send the tuple to the receiver */
2480 (void) tstate->dest->receiveSlot(slot, tstate->dest);
2481
2482 /* clean up */
2483 ExecClearTuple(slot);
2484}
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
TupleDesc tts_tupleDescriptor
Definition tuptable.h:122
bool * tts_isnull
Definition tuptable.h:126
Datum * tts_values
Definition tuptable.h:124
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:457

References ExecClearTuple(), ExecStoreVirtualTuple(), fb(), TupleDescData::natts, 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)
extern

Definition at line 2522 of file execTuples.c.

2523{
2524 tstate->dest->rShutdown(tstate->dest);
2525 /* note that destroying the dest is not ours to do */
2527 pfree(tstate);
2528}
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)

References ExecDropSingleTupleTableSlot(), fb(), and pfree().

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

◆ EstimateTupleHashTableSpace()

Size EstimateTupleHashTableSpace ( double  nentries,
Size  tupleWidth,
Size  additionalsize 
)
extern

Definition at line 321 of file execGrouping.c.

324{
326 double tuples_space;
327
328 /* First estimate the space needed for the simplehash table */
330
331 /* Give up if that's already too big */
332 if (sh_space >= SIZE_MAX)
333 return sh_space;
334
335 /*
336 * Compute space needed for hashed tuples with additional data. nentries
337 * must be somewhat sane, so it should be safe to compute this product.
338 *
339 * We assume that the hashed tuples will be kept in a BumpContext so that
340 * there is not additional per-tuple overhead.
341 *
342 * (Note that this is only accurate if MEMORY_CONTEXT_CHECKING is off,
343 * else bump.c will add a MemoryChunk header to each tuple. However, it
344 * seems undesirable for debug builds to make different planning choices
345 * than production builds, so we assume the production behavior always.)
346 */
349 MAXALIGN(additionalsize));
350
351 /*
352 * Check for size_t overflow. This coding is trickier than it may appear,
353 * because on 64-bit machines SIZE_MAX cannot be represented exactly as a
354 * double. We must cast it explicitly to suppress compiler warnings about
355 * an inexact conversion, and we must trust that any double value that
356 * compares strictly less than "(double) SIZE_MAX" will cast to a
357 * representable size_t value.
358 */
359 if (sh_space + tuples_space >= (double) SIZE_MAX)
360 return SIZE_MAX;
361
362 /* We don't bother estimating size of the miscellaneous overhead data */
363 return (Size) (sh_space + tuples_space);
364}
#define SizeofMinimalTupleHeader

References fb(), MAXALIGN, and SizeofMinimalTupleHeader.

Referenced by EstimateSetOpHashTableSpace(), and EstimateSubplanHashTableSpace().

◆ EvalPlanQual()

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

Definition at line 2653 of file execMain.c.

2655{
2656 TupleTableSlot *slot;
2658
2659 Assert(rti > 0);
2660
2661 /*
2662 * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2663 */
2664 EvalPlanQualBegin(epqstate);
2665
2666 /*
2667 * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
2668 * an unnecessary copy.
2669 */
2670 testslot = EvalPlanQualSlot(epqstate, relation, rti);
2671 if (testslot != inputslot)
2672 ExecCopySlot(testslot, inputslot);
2673
2674 /*
2675 * Mark that an EPQ tuple is available for this relation. (If there is
2676 * more than one result relation, the others remain marked as having no
2677 * tuple available.)
2678 */
2679 epqstate->relsubs_done[rti - 1] = false;
2680 epqstate->relsubs_blocked[rti - 1] = false;
2681
2682 /*
2683 * Run the EPQ query. We assume it will return at most one tuple.
2684 */
2685 slot = EvalPlanQualNext(epqstate);
2686
2687 /*
2688 * If we got a tuple, force the slot to materialize the tuple so that it
2689 * is not dependent on any local state in the EPQ query (in particular,
2690 * it's highly likely that the slot contains references to any pass-by-ref
2691 * datums that may be present in copyTuple). As with the next step, this
2692 * is to guard against early re-use of the EPQ query.
2693 */
2694 if (!TupIsNull(slot))
2695 ExecMaterializeSlot(slot);
2696
2697 /*
2698 * Clear out the test tuple, and mark that no tuple is available here.
2699 * This is needed in case the EPQ state is re-used to test a tuple for a
2700 * different target relation.
2701 */
2703 epqstate->relsubs_blocked[rti - 1] = true;
2704
2705 return slot;
2706}
TupleTableSlot * EvalPlanQualSlot(EPQState *epqstate, Relation relation, Index rti)
Definition execMain.c:2780
void EvalPlanQualBegin(EPQState *epqstate)
Definition execMain.c:2935
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition execMain.c:2919
bool * relsubs_blocked
Definition execnodes.h:1358
bool * relsubs_done
Definition execnodes.h:1349
#define TupIsNull(slot)
Definition tuptable.h:309
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition tuptable.h:524
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition tuptable.h:475

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)
extern

Definition at line 2935 of file execMain.c.

2936{
2937 EState *parentestate = epqstate->parentestate;
2938 EState *recheckestate = epqstate->recheckestate;
2939
2940 if (recheckestate == NULL)
2941 {
2942 /* First time through, so create a child EState */
2943 EvalPlanQualStart(epqstate, epqstate->plan);
2944 }
2945 else
2946 {
2947 /*
2948 * We already have a suitable child EPQ tree, so just reset it.
2949 */
2950 Index rtsize = parentestate->es_range_table_size;
2952
2953 /*
2954 * Reset the relsubs_done[] flags to equal relsubs_blocked[], so that
2955 * the EPQ run will never attempt to fetch tuples from blocked target
2956 * relations.
2957 */
2958 memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
2959 rtsize * sizeof(bool));
2960
2961 /* Recopy current values of parent parameters */
2962 if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2963 {
2964 int i;
2965
2966 /*
2967 * Force evaluation of any InitPlan outputs that could be needed
2968 * by the subplan, just in case they got reset since
2969 * EvalPlanQualStart (see comments therein).
2970 */
2971 ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2972 GetPerTupleExprContext(parentestate));
2973
2974 i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2975
2976 while (--i >= 0)
2977 {
2978 /* copy value if any, but not execPlan link */
2979 recheckestate->es_param_exec_vals[i].value =
2980 parentestate->es_param_exec_vals[i].value;
2981 recheckestate->es_param_exec_vals[i].isnull =
2982 parentestate->es_param_exec_vals[i].isnull;
2983 }
2984 }
2985
2986 /*
2987 * Mark child plan tree as needing rescan at all scan nodes. The
2988 * first ExecProcNode will take care of actually doing the rescan.
2989 */
2990 rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2991 epqstate->epqParam);
2992 }
2993}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:814
unsigned int Index
Definition c.h:628
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition execMain.c:3002
#define GetPerTupleExprContext(estate)
Definition executor.h:656
int i
Definition isn.c:77
void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext)
static int list_length(const List *l)
Definition pg_list.h:152
Plan * plan
Definition execnodes.h:1321
int epqParam
Definition execnodes.h:1304
EState * parentestate
Definition execnodes.h:1303
EState * recheckestate
Definition execnodes.h:1335
PlanState * recheckplanstate
Definition execnodes.h:1360
bool isnull
Definition params.h:149
Datum value
Definition params.h:148
List * paramExecTypes
Definition plannodes.h:147

References bms_add_member(), EPQState::epqParam, EState::es_param_exec_vals, EState::es_plannedstmt, EState::es_range_table_size, EvalPlanQualStart(), ExecSetParamPlanMulti(), fb(), GetPerTupleExprContext, i, ParamExecData::isnull, list_length(), NIL, PlannedStmt::paramExecTypes, EPQState::parentestate, 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)
extern

Definition at line 3183 of file execMain.c.

3184{
3185 EState *estate = epqstate->recheckestate;
3186 Index rtsize;
3187 MemoryContext oldcontext;
3188 ListCell *l;
3189
3191
3192 /*
3193 * We may have a tuple table, even if EPQ wasn't started, because we allow
3194 * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
3195 */
3196 if (epqstate->tuple_table != NIL)
3197 {
3198 memset(epqstate->relsubs_slot, 0,
3199 rtsize * sizeof(TupleTableSlot *));
3200 ExecResetTupleTable(epqstate->tuple_table, true);
3201 epqstate->tuple_table = NIL;
3202 }
3203
3204 /* EPQ wasn't started, nothing further to do */
3205 if (estate == NULL)
3206 return;
3207
3208 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3209
3210 ExecEndNode(epqstate->recheckplanstate);
3211
3212 foreach(l, estate->es_subplanstates)
3213 {
3215
3217 }
3218
3219 /* throw away the per-estate tuple table, some node may have used it */
3220 ExecResetTupleTable(estate->es_tupleTable, false);
3221
3222 /* Close any result and trigger target relations attached to this EState */
3224
3225 MemoryContextSwitchTo(oldcontext);
3226
3227 /*
3228 * NULLify the partition directory before freeing the executor state.
3229 * Since EvalPlanQualStart() just borrowed the parent EState's directory,
3230 * we'd better leave it up to the parent to delete it.
3231 */
3232 estate->es_partition_directory = NULL;
3233
3234 FreeExecutorState(estate);
3235
3236 /* Mark EPQState idle */
3237 epqstate->origslot = NULL;
3238 epqstate->recheckestate = NULL;
3239 epqstate->recheckplanstate = NULL;
3240 epqstate->relsubs_rowmark = NULL;
3241 epqstate->relsubs_done = NULL;
3242 epqstate->relsubs_blocked = NULL;
3243}
void ExecCloseResultRelations(EState *estate)
Definition execMain.c:1579
void ExecEndNode(PlanState *node)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
void FreeExecutorState(EState *estate)
Definition execUtils.c:192
#define lfirst(lc)
Definition pg_list.h:172
ExecAuxRowMark ** relsubs_rowmark
Definition execnodes.h:1342
TupleTableSlot * origslot
Definition execnodes.h:1330
TupleTableSlot ** relsubs_slot
Definition execnodes.h:1314
List * tuple_table
Definition execnodes.h:1313
PartitionDirectory es_partition_directory
Definition execnodes.h:694

References EState::es_partition_directory, EState::es_query_cxt, EState::es_range_table_size, EState::es_subplanstates, EState::es_tupleTable, ExecCloseResultRelations(), ExecEndNode(), ExecResetTupleTable(), fb(), 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 
)
extern

Definition at line 2808 of file execMain.c.

2809{
2810 ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1];
2812 Datum datum;
2813 bool isNull;
2814
2815 Assert(earm != NULL);
2816 Assert(epqstate->origslot != NULL);
2817
2818 erm = earm->rowmark;
2819
2820 if (RowMarkRequiresRowShareLock(erm->markType))
2821 elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2822
2823 /* if child rel, must check whether it produced this row */
2824 if (erm->rti != erm->prti)
2825 {
2826 Oid tableoid;
2827
2828 datum = ExecGetJunkAttribute(epqstate->origslot,
2829 earm->toidAttNo,
2830 &isNull);
2831 /* non-locked rels could be on the inside of outer joins */
2832 if (isNull)
2833 return false;
2834
2835 tableoid = DatumGetObjectId(datum);
2836
2837 Assert(OidIsValid(erm->relid));
2838 if (tableoid != erm->relid)
2839 {
2840 /* this child is inactive right now */
2841 return false;
2842 }
2843 }
2844
2845 if (erm->markType == ROW_MARK_REFERENCE)
2846 {
2847 Assert(erm->relation != NULL);
2848
2849 /* fetch the tuple's ctid */
2850 datum = ExecGetJunkAttribute(epqstate->origslot,
2851 earm->ctidAttNo,
2852 &isNull);
2853 /* non-locked rels could be on the inside of outer joins */
2854 if (isNull)
2855 return false;
2856
2857 /* fetch requests on foreign tables must be passed to their FDW */
2858 if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2859 {
2860 FdwRoutine *fdwroutine;
2861 bool updated = false;
2862
2863 fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2864 /* this should have been checked already, but let's be safe */
2865 if (fdwroutine->RefetchForeignRow == NULL)
2866 ereport(ERROR,
2868 errmsg("cannot lock rows in foreign table \"%s\"",
2869 RelationGetRelationName(erm->relation))));
2870
2871 fdwroutine->RefetchForeignRow(epqstate->recheckestate,
2872 erm,
2873 datum,
2874 slot,
2875 &updated);
2876 if (TupIsNull(slot))
2877 elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2878
2879 /*
2880 * Ideally we'd insist on updated == false here, but that assumes
2881 * that FDWs can track that exactly, which they might not be able
2882 * to. So just ignore the flag.
2883 */
2884 return true;
2885 }
2886 else
2887 {
2888 /* ordinary table, fetch the tuple */
2889 if (!table_tuple_fetch_row_version(erm->relation,
2891 SnapshotAny, slot))
2892 elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2893 return true;
2894 }
2895 }
2896 else
2897 {
2898 Assert(erm->markType == ROW_MARK_COPY);
2899
2900 /* fetch the whole-row Var for the relation */
2901 datum = ExecGetJunkAttribute(epqstate->origslot,
2902 earm->wholeAttNo,
2903 &isNull);
2904 /* non-locked rels could be on the inside of outer joins */
2905 if (isNull)
2906 return false;
2907
2908 ExecStoreHeapTupleDatum(datum, slot);
2909 return true;
2910 }
2911}
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
static Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition executor.h:225
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition foreign.c:443
#define RowMarkRequiresRowShareLock(marktype)
Definition plannodes.h:1544
@ ROW_MARK_COPY
Definition plannodes.h:1541
@ ROW_MARK_REFERENCE
Definition plannodes.h:1540
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:252
unsigned int Oid
#define SnapshotAny
Definition snapmgr.h:33
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:1275

References Assert, DatumGetObjectId(), DatumGetPointer(), elog, ereport, errcode(), errmsg(), ERROR, ExecGetJunkAttribute(), ExecStoreHeapTupleDatum(), fb(), GetFdwRoutineForRelation(), OidIsValid, EPQState::origslot, EPQState::recheckestate, FdwRoutine::RefetchForeignRow, RelationGetRelationName, EPQState::relsubs_rowmark, ROW_MARK_COPY, ROW_MARK_REFERENCE, RowMarkRequiresRowShareLock, SnapshotAny, table_tuple_fetch_row_version(), and TupIsNull.

Referenced by ExecScanFetch().

◆ EvalPlanQualInit()

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

Definition at line 2722 of file execMain.c.

2725{
2726 Index rtsize = parentestate->es_range_table_size;
2727
2728 /* initialize data not changing over EPQState's lifetime */
2729 epqstate->parentestate = parentestate;
2730 epqstate->epqParam = epqParam;
2731 epqstate->resultRelations = resultRelations;
2732
2733 /*
2734 * Allocate space to reference a slot for each potential rti - do so now
2735 * rather than in EvalPlanQualBegin(), as done for other dynamically
2736 * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2737 * that *may* need EPQ later, without forcing the overhead of
2738 * EvalPlanQualBegin().
2739 */
2740 epqstate->tuple_table = NIL;
2742
2743 /* ... and remember data that EvalPlanQualBegin will need */
2744 epqstate->plan = subplan;
2745 epqstate->arowMarks = auxrowmarks;
2746
2747 /* ... and mark the EPQ state inactive */
2748 epqstate->origslot = NULL;
2749 epqstate->recheckestate = NULL;
2750 epqstate->recheckplanstate = NULL;
2751 epqstate->relsubs_rowmark = NULL;
2752 epqstate->relsubs_done = NULL;
2753 epqstate->relsubs_blocked = NULL;
2754}
#define palloc0_array(type, count)
Definition fe_memutils.h:77
List * resultRelations
Definition execnodes.h:1305
List * arowMarks
Definition execnodes.h:1322

References EPQState::arowMarks, EPQState::epqParam, EState::es_range_table_size, fb(), NIL, EPQState::origslot, palloc0_array, 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)
extern

Definition at line 2919 of file execMain.c.

2920{
2921 MemoryContext oldcontext;
2922 TupleTableSlot *slot;
2923
2924 oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2925 slot = ExecProcNode(epqstate->recheckplanstate);
2926 MemoryContextSwitchTo(oldcontext);
2927
2928 return slot;
2929}
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition executor.h:314

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 
)
extern

Definition at line 2763 of file execMain.c.

2764{
2765 /* If we have a live EPQ query, shut it down */
2766 EvalPlanQualEnd(epqstate);
2767 /* And set/change the plan pointer */
2768 epqstate->plan = subplan;
2769 /* The rowmarks depend on the plan, too */
2770 epqstate->arowMarks = auxrowmarks;
2771}
void EvalPlanQualEnd(EPQState *epqstate)
Definition execMain.c:3183

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2780 of file execMain.c.

2782{
2783 TupleTableSlot **slot;
2784
2785 Assert(relation);
2786 Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2787 slot = &epqstate->relsubs_slot[rti - 1];
2788
2789 if (*slot == NULL)
2790 {
2791 MemoryContext oldcontext;
2792
2793 oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2794 *slot = table_slot_create(relation, &epqstate->tuple_table);
2795 MemoryContextSwitchTo(oldcontext);
2796 }
2797
2798 return *slot;
2799}
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition tableam.c:92

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

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

◆ exec_rt_fetch()

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)
extern

Definition at line 583 of file execUtils.c.

585{
586 planstate->ps_ProjInfo =
588 planstate->ps_ExprContext,
589 planstate->ps_ResultTupleSlot,
590 planstate,
591 inputDesc);
592}
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition execExpr.c:370
Plan * plan
Definition execnodes.h:1167
TupleTableSlot * ps_ResultTupleSlot
Definition execnodes.h:1205
ProjectionInfo * ps_ProjInfo
Definition execnodes.h:1207
List * targetlist
Definition plannodes.h:229

References ExecBuildProjectionInfo(), fb(), 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()

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)
extern

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)
extern

Definition at line 692 of file execUtils.c.

693{
694 TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
695
696 ExecSetSlotDescriptor(slot, tupDesc);
697}
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)

References ExecSetSlotDescriptor(), and fb().

Referenced by ExecWorkTableScan().

◆ ExecBuildAggTrans()

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

◆ ExecBuildAuxRowMark()

ExecAuxRowMark * ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)
extern

Definition at line 2583 of file execMain.c.

2584{
2586 char resname[32];
2587
2588 aerm->rowmark = erm;
2589
2590 /* Look up the resjunk columns associated with this rowmark */
2591 if (erm->markType != ROW_MARK_COPY)
2592 {
2593 /* need ctid for all methods other than COPY */
2594 snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2595 aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2596 resname);
2597 if (!AttributeNumberIsValid(aerm->ctidAttNo))
2598 elog(ERROR, "could not find junk %s column", resname);
2599 }
2600 else
2601 {
2602 /* need wholerow if COPY */
2603 snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2604 aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2605 resname);
2606 if (!AttributeNumberIsValid(aerm->wholeAttNo))
2607 elog(ERROR, "could not find junk %s column", resname);
2608 }
2609
2610 /* if child rel, need tableoid */
2611 if (erm->rti != erm->prti)
2612 {
2613 snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2614 aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2615 resname);
2616 if (!AttributeNumberIsValid(aerm->toidAttNo))
2617 elog(ERROR, "could not find junk %s column", resname);
2618 }
2619
2620 return aerm;
2621}
#define AttributeNumberIsValid(attributeNumber)
Definition attnum.h:34
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition execJunk.c:222
#define palloc0_object(type)
Definition fe_memutils.h:75
#define snprintf
Definition port.h:260

References AttributeNumberIsValid, elog, ERROR, ExecFindJunkAttributeInTlist(), fb(), palloc0_object, ROW_MARK_COPY, and snprintf.

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 
)
extern

Definition at line 4459 of file execExpr.c.

4466{
4468 ExprEvalStep scratch = {0};
4469 int maxatt = -1;
4471 ListCell *lc;
4472
4473 /*
4474 * When no columns are actually compared, the result's always true. See
4475 * special case in ExecQual().
4476 */
4477 if (numCols == 0)
4478 return NULL;
4479
4480 state->expr = NULL;
4481 state->flags = EEO_FLAG_IS_QUAL;
4482 state->parent = parent;
4483
4484 scratch.resvalue = &state->resvalue;
4485 scratch.resnull = &state->resnull;
4486
4487 /* compute max needed attribute */
4488 for (int natt = 0; natt < numCols; natt++)
4489 {
4490 int attno = keyColIdx[natt];
4491
4492 if (attno > maxatt)
4493 maxatt = attno;
4494 }
4495 Assert(maxatt >= 0);
4496
4497 /* push deform steps */
4499 scratch.d.fetch.last_var = maxatt;
4500 scratch.d.fetch.fixed = false;
4501 scratch.d.fetch.known_desc = ldesc;
4502 scratch.d.fetch.kind = lops;
4505
4507 scratch.d.fetch.last_var = maxatt;
4508 scratch.d.fetch.fixed = false;
4509 scratch.d.fetch.known_desc = rdesc;
4510 scratch.d.fetch.kind = rops;
4513
4514 /*
4515 * Start comparing at the last field (least significant sort key). That's
4516 * the most likely to be different if we are dealing with sorted input.
4517 */
4518 for (int natt = numCols; --natt >= 0;)
4519 {
4520 int attno = keyColIdx[natt];
4523 Oid foid = eqfunctions[natt];
4524 Oid collid = collations[natt];
4525 FmgrInfo *finfo;
4526 FunctionCallInfo fcinfo;
4528
4529 /* Check permission to call function */
4531 if (aclresult != ACLCHECK_OK)
4533
4535
4536 /* Set up the primary fmgr lookup information */
4537 finfo = palloc0_object(FmgrInfo);
4538 fcinfo = palloc0(SizeForFunctionCallInfo(2));
4539 fmgr_info(foid, finfo);
4540 fmgr_info_set_expr(NULL, finfo);
4541 InitFunctionCallInfoData(*fcinfo, finfo, 2,
4542 collid, NULL, NULL);
4543
4544 /* left arg */
4545 scratch.opcode = EEOP_INNER_VAR;
4546 scratch.d.var.attnum = attno - 1;
4547 scratch.d.var.vartype = latt->atttypid;
4548 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4549 scratch.resvalue = &fcinfo->args[0].value;
4550 scratch.resnull = &fcinfo->args[0].isnull;
4552
4553 /* right arg */
4554 scratch.opcode = EEOP_OUTER_VAR;
4555 scratch.d.var.attnum = attno - 1;
4556 scratch.d.var.vartype = ratt->atttypid;
4557 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4558 scratch.resvalue = &fcinfo->args[1].value;
4559 scratch.resnull = &fcinfo->args[1].isnull;
4561
4562 /* evaluate distinctness */
4563 scratch.opcode = EEOP_NOT_DISTINCT;
4564 scratch.d.func.finfo = finfo;
4565 scratch.d.func.fcinfo_data = fcinfo;
4566 scratch.d.func.fn_addr = finfo->fn_addr;
4567 scratch.d.func.nargs = 2;
4568 scratch.resvalue = &state->resvalue;
4569 scratch.resnull = &state->resnull;
4571
4572 /* then emit EEOP_QUAL to detect if result is false (or null) */
4573 scratch.opcode = EEOP_QUAL;
4574 scratch.d.qualexpr.jumpdone = -1;
4575 scratch.resvalue = &state->resvalue;
4576 scratch.resnull = &state->resnull;
4579 state->steps_len - 1);
4580 }
4581
4582 /* adjust jump targets */
4583 foreach(lc, adjust_jumps)
4584 {
4585 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4586
4587 Assert(as->opcode == EEOP_QUAL);
4588 Assert(as->d.qualexpr.jumpdone == -1);
4589 as->d.qualexpr.jumpdone = state->steps_len;
4590 }
4591
4592 scratch.resvalue = NULL;
4593 scratch.resnull = NULL;
4594 scratch.opcode = EEOP_DONE_RETURN;
4596
4598
4599 return state;
4600}
AclResult
Definition acl.h:182
@ ACLCHECK_OK
Definition acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2654
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3836
Oid collid
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition execExpr.c:2671
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition execExpr.c:3057
static void ExecReadyExpr(ExprState *state)
Definition execExpr.c:902
@ EEOP_NOT_DISTINCT
Definition execExpr.h:190
@ EEOP_DONE_RETURN
Definition execExpr.h:69
@ EEOP_INNER_VAR
Definition execExpr.h:82
@ EEOP_QUAL
Definition execExpr.h:148
@ EEOP_INNER_FETCHSOME
Definition execExpr.h:75
@ EEOP_OUTER_FETCHSOME
Definition execExpr.h:76
@ EEOP_OUTER_VAR
Definition execExpr.h:83
#define EEO_FLAG_IS_QUAL
Definition execnodes.h:76
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:128
#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:1758
void * palloc0(Size size)
Definition mcxt.c:1417
Oid GetUserId(void)
Definition miscinit.c:469
#define InvokeFunctionExecuteHook(objectId)
@ OBJECT_FUNCTION
#define ACL_EXECUTE
Definition parsenodes.h:83
FormData_pg_attribute * Form_pg_attribute
#define lfirst_int(lc)
Definition pg_list.h:173
@ VAR_RETURNING_DEFAULT
Definition primnodes.h:256
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:87
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert, collid, EEO_FLAG_IS_QUAL, EEOP_DONE_RETURN, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, EEOP_NOT_DISTINCT, EEOP_OUTER_FETCHSOME, EEOP_OUTER_VAR, EEOP_QUAL, ExecComputeSlotInfo(), ExecReadyExpr(), ExprEvalPushStep(), fb(), fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_addr, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvokeFunctionExecuteHook, NullableDatum::isnull, lappend_int(), lfirst_int, makeNode, NIL, object_aclcheck(), OBJECT_FUNCTION, palloc0(), palloc0_object, SizeForFunctionCallInfo, TupleDescAttr(), NullableDatum::value, and VAR_RETURNING_DEFAULT.

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

◆ ExecBuildHash32Expr()

ExprState * ExecBuildHash32Expr ( TupleDesc  desc,
const TupleTableSlotOps ops,
const Oid hashfunc_oids,
const List collations,
const List hash_exprs,
const bool opstrict,
PlanState parent,
uint32  init_value,
bool  keep_nulls 
)
extern

Definition at line 4294 of file execExpr.c.

4298{
4300 ExprEvalStep scratch = {0};
4301 NullableDatum *iresult = NULL;
4303 ListCell *lc;
4304 ListCell *lc2;
4306 intptr_t opcode;
4308
4309 Assert(num_exprs == list_length(collations));
4310
4311 state->parent = parent;
4312
4313 /* Insert setup steps as needed. */
4315
4316 /*
4317 * Make a place to store intermediate hash values between subsequent
4318 * hashing of individual expressions. We only need this if there is more
4319 * than one expression to hash or an initial value plus one expression.
4320 */
4321 if ((int64) num_exprs + (init_value != 0) > 1)
4322 iresult = palloc_object(NullableDatum);
4323
4324 if (init_value == 0)
4325 {
4326 /*
4327 * No initial value, so we can assign the result of the hash function
4328 * for the first hash_expr without having to concern ourselves with
4329 * combining the result with any initial value.
4330 */
4332 opcode = EEOP_HASHDATUM_FIRST;
4333 }
4334 else
4335 {
4336 /*
4337 * Set up operation to set the initial value. Normally we store this
4338 * in the intermediate hash value location, but if there are no exprs
4339 * to hash, store it in the ExprState's result field.
4340 */
4342 scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4343 scratch.resvalue = num_exprs > 0 ? &iresult->value : &state->resvalue;
4344 scratch.resnull = num_exprs > 0 ? &iresult->isnull : &state->resnull;
4345
4347
4348 /*
4349 * When using an initial value use the NEXT32/NEXT32_STRICT ops as the
4350 * FIRST/FIRST_STRICT ops would overwrite the stored initial value.
4351 */
4353 opcode = EEOP_HASHDATUM_NEXT32;
4354 }
4355
4356 forboth(lc, hash_exprs, lc2, collations)
4357 {
4358 Expr *expr = (Expr *) lfirst(lc);
4359 FmgrInfo *finfo;
4360 FunctionCallInfo fcinfo;
4361 int i = foreach_current_index(lc);
4362 Oid funcid;
4363 Oid inputcollid = lfirst_oid(lc2);
4364
4365 funcid = hashfunc_oids[i];
4366
4367 /* Allocate hash function lookup data. */
4368 finfo = palloc0_object(FmgrInfo);
4369 fcinfo = palloc0(SizeForFunctionCallInfo(1));
4370
4371 fmgr_info(funcid, finfo);
4372
4373 /*
4374 * Build the steps to evaluate the hash function's argument have it so
4375 * the value of that is stored in the 0th argument of the hash func.
4376 */
4377 ExecInitExprRec(expr,
4378 state,
4379 &fcinfo->args[0].value,
4380 &fcinfo->args[0].isnull);
4381
4382 if (i == num_exprs - 1)
4383 {
4384 /* the result for hashing the final expr is stored in the state */
4385 scratch.resvalue = &state->resvalue;
4386 scratch.resnull = &state->resnull;
4387 }
4388 else
4389 {
4390 Assert(iresult != NULL);
4391
4392 /* intermediate values are stored in an intermediate result */
4393 scratch.resvalue = &iresult->value;
4394 scratch.resnull = &iresult->isnull;
4395 }
4396
4397 /*
4398 * NEXT32 opcodes need to look at the intermediate result. We might
4399 * as well just set this for all ops. FIRSTs won't look at it.
4400 */
4401 scratch.d.hashdatum.iresult = iresult;
4402
4403 /* Initialize function call parameter structure too */
4404 InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4405
4406 scratch.d.hashdatum.finfo = finfo;
4407 scratch.d.hashdatum.fcinfo_data = fcinfo;
4408 scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4409
4410 scratch.opcode = opstrict[i] && !keep_nulls ? strict_opcode : opcode;
4411 scratch.d.hashdatum.jumpdone = -1;
4412
4414 adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1);
4415
4416 /*
4417 * For subsequent keys we must combine the hash value with the
4418 * previous hashes.
4419 */
4421 opcode = EEOP_HASHDATUM_NEXT32;
4422 }
4423
4424 /* adjust jump targets */
4425 foreach(lc, adjust_jumps)
4426 {
4427 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4428
4429 Assert(as->opcode == EEOP_HASHDATUM_FIRST ||
4430 as->opcode == EEOP_HASHDATUM_FIRST_STRICT ||
4431 as->opcode == EEOP_HASHDATUM_NEXT32 ||
4432 as->opcode == EEOP_HASHDATUM_NEXT32_STRICT);
4433 Assert(as->d.hashdatum.jumpdone == -1);
4434 as->d.hashdatum.jumpdone = state->steps_len;
4435 }
4436
4437 scratch.resvalue = NULL;
4438 scratch.resnull = NULL;
4439 scratch.opcode = EEOP_DONE_RETURN;
4441
4443
4444 return state;
4445}
int64_t int64
Definition c.h:543
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition execExpr.c:919
static void ExecCreateExprSetupSteps(ExprState *state, Node *node)
Definition execExpr.c:2876
@ EEOP_HASHDATUM_NEXT32_STRICT
Definition execExpr.h:259
@ EEOP_HASHDATUM_FIRST_STRICT
Definition execExpr.h:257
@ EEOP_HASHDATUM_NEXT32
Definition execExpr.h:258
@ EEOP_HASHDATUM_FIRST
Definition execExpr.h:256
@ EEOP_HASHDATUM_SET_INITVAL
Definition execExpr.h:255
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:518
#define foreach_current_index(var_or_cell)
Definition pg_list.h:403
#define lfirst_oid(lc)
Definition pg_list.h:174
static Datum UInt32GetDatum(uint32 X)
Definition postgres.h:242
Definition nodes.h:135

References FunctionCallInfoBaseData::args, Assert, EEOP_DONE_RETURN, EEOP_HASHDATUM_FIRST, EEOP_HASHDATUM_FIRST_STRICT, EEOP_HASHDATUM_NEXT32, EEOP_HASHDATUM_NEXT32_STRICT, EEOP_HASHDATUM_SET_INITVAL, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), fb(), fmgr_info(), FmgrInfo::fn_addr, forboth, foreach_current_index, i, InitFunctionCallInfoData, NullableDatum::isnull, lappend_int(), lfirst, lfirst_int, lfirst_oid, list_length(), makeNode, NIL, palloc0(), palloc0_object, palloc_object, SizeForFunctionCallInfo, UInt32GetDatum(), and NullableDatum::value.

Referenced by ExecInitHashJoin().

◆ ExecBuildHash32FromAttrs()

ExprState * ExecBuildHash32FromAttrs ( TupleDesc  desc,
const TupleTableSlotOps ops,
FmgrInfo hashfunctions,
Oid collations,
int  numCols,
AttrNumber keyColIdx,
PlanState parent,
uint32  init_value 
)
extern

Definition at line 4135 of file execExpr.c.

4139{
4141 ExprEvalStep scratch = {0};
4142 NullableDatum *iresult = NULL;
4143 intptr_t opcode;
4145
4146 Assert(numCols >= 0);
4147
4148 state->parent = parent;
4149
4150 /*
4151 * Make a place to store intermediate hash values between subsequent
4152 * hashing of individual columns. We only need this if there is more than
4153 * one column to hash or an initial value plus one column.
4154 */
4155 if ((int64) numCols + (init_value != 0) > 1)
4156 iresult = palloc_object(NullableDatum);
4157
4158 /* find the highest attnum so we deform the tuple to that point */
4159 for (int i = 0; i < numCols; i++)
4160 last_attnum = Max(last_attnum, keyColIdx[i]);
4161
4163 scratch.d.fetch.last_var = last_attnum;
4164 scratch.d.fetch.fixed = false;
4165 scratch.d.fetch.kind = ops;
4166 scratch.d.fetch.known_desc = desc;
4169
4170 if (init_value == 0)
4171 {
4172 /*
4173 * No initial value, so we can assign the result of the hash function
4174 * for the first attribute without having to concern ourselves with
4175 * combining the result with any initial value.
4176 */
4177 opcode = EEOP_HASHDATUM_FIRST;
4178 }
4179 else
4180 {
4181 /*
4182 * Set up operation to set the initial value. Normally we store this
4183 * in the intermediate hash value location, but if there are no
4184 * columns to hash, store it in the ExprState's result field.
4185 */
4187 scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4188 scratch.resvalue = numCols > 0 ? &iresult->value : &state->resvalue;
4189 scratch.resnull = numCols > 0 ? &iresult->isnull : &state->resnull;
4190
4192
4193 /*
4194 * When using an initial value use the NEXT32 ops as the FIRST ops
4195 * would overwrite the stored initial value.
4196 */
4197 opcode = EEOP_HASHDATUM_NEXT32;
4198 }
4199
4200 for (int i = 0; i < numCols; i++)
4201 {
4202 FmgrInfo *finfo;
4203 FunctionCallInfo fcinfo;
4204 Oid inputcollid = collations[i];
4205 AttrNumber attnum = keyColIdx[i] - 1;
4206
4207 finfo = &hashfunctions[i];
4208 fcinfo = palloc0(SizeForFunctionCallInfo(1));
4209
4210 /* Initialize function call parameter structure too */
4211 InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4212
4213 /*
4214 * Fetch inner Var for this attnum and store it in the 1st arg of the
4215 * hash func.
4216 */
4217 scratch.opcode = EEOP_INNER_VAR;
4218 scratch.resvalue = &fcinfo->args[0].value;
4219 scratch.resnull = &fcinfo->args[0].isnull;
4220 scratch.d.var.attnum = attnum;
4221 scratch.d.var.vartype = TupleDescAttr(desc, attnum)->atttypid;
4222 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4223
4225
4226 /* Call the hash function */
4227 scratch.opcode = opcode;
4228
4229 if (i == numCols - 1)
4230 {
4231 /*
4232 * The result for hashing the final column is stored in the
4233 * ExprState.
4234 */
4235 scratch.resvalue = &state->resvalue;
4236 scratch.resnull = &state->resnull;
4237 }
4238 else
4239 {
4240 Assert(iresult != NULL);
4241
4242 /* intermediate values are stored in an intermediate result */
4243 scratch.resvalue = &iresult->value;
4244 scratch.resnull = &iresult->isnull;
4245 }
4246
4247 /*
4248 * NEXT32 opcodes need to look at the intermediate result. We might
4249 * as well just set this for all ops. FIRSTs won't look at it.
4250 */
4251 scratch.d.hashdatum.iresult = iresult;
4252
4253 scratch.d.hashdatum.finfo = finfo;
4254 scratch.d.hashdatum.fcinfo_data = fcinfo;
4255 scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4256 scratch.d.hashdatum.jumpdone = -1;
4257
4259
4260 /* subsequent attnums must be combined with the previous */
4261 opcode = EEOP_HASHDATUM_NEXT32;
4262 }
4263
4264 scratch.resvalue = NULL;
4265 scratch.resnull = NULL;
4266 scratch.opcode = EEOP_DONE_RETURN;
4268
4270
4271 return state;
4272}
int16 AttrNumber
Definition attnum.h:21
int16 attnum

References FunctionCallInfoBaseData::args, Assert, attnum, EEOP_DONE_RETURN, EEOP_HASHDATUM_FIRST, EEOP_HASHDATUM_NEXT32, EEOP_HASHDATUM_SET_INITVAL, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, ExecComputeSlotInfo(), ExecReadyExpr(), ExprEvalPushStep(), fb(), FmgrInfo::fn_addr, i, InitFunctionCallInfoData, NullableDatum::isnull, makeNode, Max, palloc0(), palloc_object, SizeForFunctionCallInfo, TupleDescAttr(), UInt32GetDatum(), NullableDatum::value, and VAR_RETURNING_DEFAULT.

Referenced by BuildTupleHashTable(), and ExecInitSubPlan().

◆ ExecBuildParamSetEqual()

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

Definition at line 4618 of file execExpr.c.

4625{
4627 ExprEvalStep scratch = {0};
4628 int maxatt = list_length(param_exprs);
4630 ListCell *lc;
4631
4632 state->expr = NULL;
4633 state->flags = EEO_FLAG_IS_QUAL;
4634 state->parent = parent;
4635
4636 scratch.resvalue = &state->resvalue;
4637 scratch.resnull = &state->resnull;
4638
4639 /* push deform steps */
4641 scratch.d.fetch.last_var = maxatt;
4642 scratch.d.fetch.fixed = false;
4643 scratch.d.fetch.known_desc = desc;
4644 scratch.d.fetch.kind = lops;
4647
4649 scratch.d.fetch.last_var = maxatt;
4650 scratch.d.fetch.fixed = false;
4651 scratch.d.fetch.known_desc = desc;
4652 scratch.d.fetch.kind = rops;
4655
4656 for (int attno = 0; attno < maxatt; attno++)
4657 {
4658 Form_pg_attribute att = TupleDescAttr(desc, attno);
4659 Oid foid = eqfunctions[attno];
4660 Oid collid = collations[attno];
4661 FmgrInfo *finfo;
4662 FunctionCallInfo fcinfo;
4664
4665 /* Check permission to call function */
4667 if (aclresult != ACLCHECK_OK)
4669
4671
4672 /* Set up the primary fmgr lookup information */
4673 finfo = palloc0_object(FmgrInfo);
4674 fcinfo = palloc0(SizeForFunctionCallInfo(2));
4675 fmgr_info(foid, finfo);
4676 fmgr_info_set_expr(NULL, finfo);
4677 InitFunctionCallInfoData(*fcinfo, finfo, 2,
4678 collid, NULL, NULL);
4679
4680 /* left arg */
4681 scratch.opcode = EEOP_INNER_VAR;
4682 scratch.d.var.attnum = attno;
4683 scratch.d.var.vartype = att->atttypid;
4684 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4685 scratch.resvalue = &fcinfo->args[0].value;
4686 scratch.resnull = &fcinfo->args[0].isnull;
4688
4689 /* right arg */
4690 scratch.opcode = EEOP_OUTER_VAR;
4691 scratch.d.var.attnum = attno;
4692 scratch.d.var.vartype = att->atttypid;
4693 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4694 scratch.resvalue = &fcinfo->args[1].value;
4695 scratch.resnull = &fcinfo->args[1].isnull;
4697
4698 /* evaluate distinctness */
4699 scratch.opcode = EEOP_NOT_DISTINCT;
4700 scratch.d.func.finfo = finfo;
4701 scratch.d.func.fcinfo_data = fcinfo;
4702 scratch.d.func.fn_addr = finfo->fn_addr;
4703 scratch.d.func.nargs = 2;
4704 scratch.resvalue = &state->resvalue;
4705 scratch.resnull = &state->resnull;
4707
4708 /* then emit EEOP_QUAL to detect if result is false (or null) */
4709 scratch.opcode = EEOP_QUAL;
4710 scratch.d.qualexpr.jumpdone = -1;
4711 scratch.resvalue = &state->resvalue;
4712 scratch.resnull = &state->resnull;
4715 state->steps_len - 1);
4716 }
4717
4718 /* adjust jump targets */
4719 foreach(lc, adjust_jumps)
4720 {
4721 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4722
4723 Assert(as->opcode == EEOP_QUAL);
4724 Assert(as->d.qualexpr.jumpdone == -1);
4725 as->d.qualexpr.jumpdone = state->steps_len;
4726 }
4727
4728 scratch.resvalue = NULL;
4729 scratch.resnull = NULL;
4730 scratch.opcode = EEOP_DONE_RETURN;
4732
4734
4735 return state;
4736}

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert, collid, EEO_FLAG_IS_QUAL, EEOP_DONE_RETURN, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, EEOP_NOT_DISTINCT, EEOP_OUTER_FETCHSOME, EEOP_OUTER_VAR, EEOP_QUAL, ExecComputeSlotInfo(), ExecReadyExpr(), ExprEvalPushStep(), fb(), fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_addr, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvokeFunctionExecuteHook, NullableDatum::isnull, lappend_int(), lfirst_int, list_length(), makeNode, NIL, object_aclcheck(), OBJECT_FUNCTION, palloc0(), palloc0_object, SizeForFunctionCallInfo, TupleDescAttr(), NullableDatum::value, and VAR_RETURNING_DEFAULT.

Referenced by ExecInitMemoize().

◆ ExecBuildProjectionInfo()

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

Definition at line 370 of file execExpr.c.

375{
378 ExprEvalStep scratch = {0};
379 ListCell *lc;
380
381 projInfo->pi_exprContext = econtext;
382 /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
383 projInfo->pi_state.type = T_ExprState;
384 state = &projInfo->pi_state;
385 state->expr = (Expr *) targetList;
386 state->parent = parent;
387 state->ext_params = NULL;
388
389 state->resultslot = slot;
390
391 /* Insert setup steps as needed */
392 ExecCreateExprSetupSteps(state, (Node *) targetList);
393
394 /* Now compile each tlist column */
395 foreach(lc, targetList)
396 {
398 Var *variable = NULL;
399 AttrNumber attnum = 0;
400 bool isSafeVar = false;
401
402 /*
403 * If tlist expression is a safe non-system Var, use the fast-path
404 * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
405 * CheckVarSlotCompatibility() during plan startup. If a source slot
406 * was provided, we make the equivalent tests here; if a slot was not
407 * provided, we assume that no check is needed because we're dealing
408 * with a non-relation-scan-level expression.
409 */
410 if (tle->expr != NULL &&
411 IsA(tle->expr, Var) &&
412 ((Var *) tle->expr)->varattno > 0)
413 {
414 /* Non-system Var, but how safe is it? */
415 variable = (Var *) tle->expr;
416 attnum = variable->varattno;
417
418 if (inputDesc == NULL)
419 isSafeVar = true; /* can't check, just assume OK */
420 else if (attnum <= inputDesc->natts)
421 {
423
424 /*
425 * If user attribute is dropped or has a type mismatch, don't
426 * use ASSIGN_*_VAR. Instead let the normal expression
427 * machinery handle it (which'll possibly error out).
428 */
429 if (!attr->attisdropped && variable->vartype == attr->atttypid)
430 {
431 isSafeVar = true;
432 }
433 }
434 }
435
436 if (isSafeVar)
437 {
438 /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
439 switch (variable->varno)
440 {
441 case INNER_VAR:
442 /* get the tuple from the inner node */
444 break;
445
446 case OUTER_VAR:
447 /* get the tuple from the outer node */
449 break;
450
451 /* INDEX_VAR is handled by default case */
452
453 default:
454
455 /*
456 * Get the tuple from the relation being scanned, or the
457 * old/new tuple slot, if old/new values were requested.
458 */
459 switch (variable->varreturningtype)
460 {
463 break;
466 state->flags |= EEO_FLAG_HAS_OLD;
467 break;
470 state->flags |= EEO_FLAG_HAS_NEW;
471 break;
472 }
473 break;
474 }
475
476 scratch.d.assign_var.attnum = attnum - 1;
477 scratch.d.assign_var.resultnum = tle->resno - 1;
479 }
480 else
481 {
482 /*
483 * Otherwise, compile the column expression normally.
484 *
485 * We can't tell the expression to evaluate directly into the
486 * result slot, as the result slot (and the exprstate for that
487 * matter) can change between executions. We instead evaluate
488 * into the ExprState's resvalue/resnull and then move.
489 */
491 &state->resvalue, &state->resnull);
492
493 /*
494 * Column might be referenced multiple times in upper nodes, so
495 * force value to R/O - but only if it could be an expanded datum.
496 */
497 if (get_typlen(exprType((Node *) tle->expr)) == -1)
499 else
500 scratch.opcode = EEOP_ASSIGN_TMP;
501 scratch.d.assign_tmp.resultnum = tle->resno - 1;
503 }
504 }
505
508
510
511 return projInfo;
512}
@ EEOP_ASSIGN_TMP
Definition execExpr.h:110
@ EEOP_ASSIGN_SCAN_VAR
Definition execExpr.h:105
@ EEOP_ASSIGN_OUTER_VAR
Definition execExpr.h:104
@ EEOP_ASSIGN_OLD_VAR
Definition execExpr.h:106
@ EEOP_ASSIGN_TMP_MAKE_RO
Definition execExpr.h:112
@ EEOP_ASSIGN_INNER_VAR
Definition execExpr.h:103
@ EEOP_DONE_NO_RETURN
Definition execExpr.h:72
@ EEOP_ASSIGN_NEW_VAR
Definition execExpr.h:107
#define EEO_FLAG_HAS_OLD
Definition execnodes.h:78
#define EEO_FLAG_HAS_NEW
Definition execnodes.h:80
int16 get_typlen(Oid typid)
Definition lsyscache.c:2347
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define lfirst_node(type, lc)
Definition pg_list.h:176
@ VAR_RETURNING_OLD
Definition primnodes.h:257
@ VAR_RETURNING_NEW
Definition primnodes.h:258
#define OUTER_VAR
Definition primnodes.h:243
#define INNER_VAR
Definition primnodes.h:242
NodeTag type
Definition execnodes.h:271

References attnum, EEO_FLAG_HAS_NEW, EEO_FLAG_HAS_OLD, EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_NEW_VAR, EEOP_ASSIGN_OLD_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_ASSIGN_TMP_MAKE_RO, EEOP_DONE_NO_RETURN, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), exprType(), fb(), get_typlen(), INNER_VAR, IsA, lfirst_node, makeNode, OUTER_VAR, TupleDescAttr(), ExprContext::type, VAR_RETURNING_DEFAULT, VAR_RETURNING_NEW, and VAR_RETURNING_OLD.

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

◆ ExecBuildSlotValueDescription()

char * ExecBuildSlotValueDescription ( Oid  reloid,
TupleTableSlot slot,
TupleDesc  tupdesc,
Bitmapset modifiedCols,
int  maxfieldlen 
)
extern

Definition at line 2395 of file execMain.c.

2400{
2403 bool write_comma = false;
2404 bool write_comma_collist = false;
2405 int i;
2407 bool table_perm = false;
2408 bool any_perm = false;
2409
2410 /*
2411 * Check if RLS is enabled and should be active for the relation; if so,
2412 * then don't return anything. Otherwise, go through normal permission
2413 * checks.
2414 */
2415 if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2416 return NULL;
2417
2419
2421
2422 /*
2423 * Check if the user has permissions to see the row. Table-level SELECT
2424 * allows access to all columns. If the user does not have table-level
2425 * SELECT then we check each column and include those the user has SELECT
2426 * rights on. Additionally, we always include columns the user provided
2427 * data for.
2428 */
2430 if (aclresult != ACLCHECK_OK)
2431 {
2432 /* Set up the buffer for the column list */
2435 }
2436 else
2437 table_perm = any_perm = true;
2438
2439 /* Make sure the tuple is fully deconstructed */
2440 slot_getallattrs(slot);
2441
2442 for (i = 0; i < tupdesc->natts; i++)
2443 {
2444 bool column_perm = false;
2445 char *val;
2446 int vallen;
2448
2449 /* ignore dropped columns */
2450 if (att->attisdropped)
2451 continue;
2452
2453 if (!table_perm)
2454 {
2455 /*
2456 * No table-level SELECT, so need to make sure they either have
2457 * SELECT rights on the column or that they have provided the data
2458 * for the column. If not, omit this column from the error
2459 * message.
2460 */
2461 aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2465 {
2466 column_perm = any_perm = true;
2467
2470 else
2471 write_comma_collist = true;
2472
2474 }
2475 }
2476
2477 if (table_perm || column_perm)
2478 {
2479 if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
2480 val = "virtual";
2481 else if (slot->tts_isnull[i])
2482 val = "null";
2483 else
2484 {
2485 Oid foutoid;
2486 bool typisvarlena;
2487
2488 getTypeOutputInfo(att->atttypid,
2489 &foutoid, &typisvarlena);
2491 }
2492
2493 if (write_comma)
2495 else
2496 write_comma = true;
2497
2498 /* truncate if needed */
2499 vallen = strlen(val);
2500 if (vallen <= maxfieldlen)
2501 appendBinaryStringInfo(&buf, val, vallen);
2502 else
2503 {
2504 vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2505 appendBinaryStringInfo(&buf, val, vallen);
2506 appendStringInfoString(&buf, "...");
2507 }
2508 }
2509 }
2510
2511 /* If we end up with zero columns being returned, then return NULL. */
2512 if (!any_perm)
2513 return NULL;
2514
2516
2517 if (!table_perm)
2518 {
2521
2522 return collist.data;
2523 }
2524
2525 return buf.data;
2526}
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition aclchk.c:3868
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4039
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
#define NameStr(name)
Definition c.h:765
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition fmgr.c:1763
long val
Definition informix.c:689
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3057
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition mbutils.c:1086
#define ACL_SELECT
Definition parsenodes.h:77
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define InvalidOid
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition rls.c:52
@ RLS_ENABLED
Definition rls.h:45
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition stringinfo.c:281
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27
static void slot_getallattrs(TupleTableSlot *slot)
Definition tuptable.h:371

References ACL_SELECT, ACLCHECK_OK, appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), bms_is_member(), buf, check_enable_rls(), fb(), FirstLowInvalidHeapAttributeNumber, getTypeOutputInfo(), GetUserId(), i, initStringInfo(), InvalidOid, NameStr, TupleDescData::natts, OidOutputFunctionCall(), pg_attribute_aclcheck(), pg_class_aclcheck(), pg_mbcliplen(), RLS_ENABLED, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TupleDescAttr(), and val.

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

◆ ExecBuildUpdateProjection()

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

Definition at line 547 of file execExpr.c.

554{
557 int nAssignableCols;
558 bool sawJunk;
560 ExprSetupInfo deform = {0, 0, 0, 0, 0, NIL};
561 ExprEvalStep scratch = {0};
562 int outerattnum;
563 ListCell *lc,
564 *lc2;
565
566 projInfo->pi_exprContext = econtext;
567 /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
568 projInfo->pi_state.type = T_ExprState;
569 state = &projInfo->pi_state;
570 if (evalTargetList)
571 state->expr = (Expr *) targetList;
572 else
573 state->expr = NULL; /* not used */
574 state->parent = parent;
575 state->ext_params = NULL;
576
577 state->resultslot = slot;
578
579 /*
580 * Examine the targetList to see how many non-junk columns there are, and
581 * to verify that the non-junk columns come before the junk ones.
582 */
583 nAssignableCols = 0;
584 sawJunk = false;
585 foreach(lc, targetList)
586 {
588
589 if (tle->resjunk)
590 sawJunk = true;
591 else
592 {
593 if (sawJunk)
594 elog(ERROR, "subplan target list is out of order");
596 }
597 }
598
599 /* We should have one targetColnos entry per non-junk column */
601 elog(ERROR, "targetColnos does not match subplan target list");
602
603 /*
604 * Build a bitmapset of the columns in targetColnos. (We could just use
605 * list_member_int() tests, but that risks O(N^2) behavior with many
606 * columns.)
607 */
609 foreach(lc, targetColnos)
610 {
612
614 }
615
616 /*
617 * We need to insert EEOP_*_FETCHSOME steps to ensure the input tuples are
618 * sufficiently deconstructed. The scan tuple must be deconstructed at
619 * least as far as the last old column we need.
620 */
621 for (int attnum = relDesc->natts; attnum > 0; attnum--)
622 {
624
625 if (attr->attisdropped)
626 continue;
628 continue;
629 deform.last_scan = attnum;
630 break;
631 }
632
633 /*
634 * If we're actually evaluating the tlist, incorporate its input
635 * requirements too; otherwise, we'll just need to fetch the appropriate
636 * number of columns of the "outer" tuple.
637 */
638 if (evalTargetList)
639 expr_setup_walker((Node *) targetList, &deform);
640 else
641 deform.last_outer = nAssignableCols;
642
644
645 /*
646 * Now generate code to evaluate the tlist's assignable expressions or
647 * fetch them from the outer tuple, incidentally validating that they'll
648 * be of the right data type. The checks above ensure that the forboth()
649 * will iterate over exactly the non-junk columns. Note that we don't
650 * bother evaluating any remaining resjunk columns.
651 */
652 outerattnum = 0;
653 forboth(lc, targetList, lc2, targetColnos)
654 {
658
659 Assert(!tle->resjunk);
660
661 /*
662 * Apply sanity checks comparable to ExecCheckPlanOutput().
663 */
667 errmsg("table row type and query-specified row type do not match"),
668 errdetail("Query has too many columns.")));
670
671 if (attr->attisdropped)
674 errmsg("table row type and query-specified row type do not match"),
675 errdetail("Query provides a value for a dropped column at ordinal position %d.",
676 targetattnum)));
677 if (exprType((Node *) tle->expr) != attr->atttypid)
680 errmsg("table row type and query-specified row type do not match"),
681 errdetail("Table has type %s at ordinal position %d, but query expects %s.",
682 format_type_be(attr->atttypid),
684 format_type_be(exprType((Node *) tle->expr)))));
685
686 /* OK, generate code to perform the assignment. */
687 if (evalTargetList)
688 {
689 /*
690 * We must evaluate the TLE's expression and assign it. We do not
691 * bother jumping through hoops for "safe" Vars like
692 * ExecBuildProjectionInfo does; this is a relatively less-used
693 * path and it doesn't seem worth expending code for that.
694 */
696 &state->resvalue, &state->resnull);
697 /* Needn't worry about read-only-ness here, either. */
698 scratch.opcode = EEOP_ASSIGN_TMP;
699 scratch.d.assign_tmp.resultnum = targetattnum - 1;
701 }
702 else
703 {
704 /* Just assign from the outer tuple. */
706 scratch.d.assign_var.attnum = outerattnum;
707 scratch.d.assign_var.resultnum = targetattnum - 1;
709 }
710 outerattnum++;
711 }
712
713 /*
714 * Now generate code to copy over any old columns that were not assigned
715 * to, and to ensure that dropped columns are set to NULL.
716 */
717 for (int attnum = 1; attnum <= relDesc->natts; attnum++)
718 {
720
721 if (attr->attisdropped)
722 {
723 /* Put a null into the ExprState's resvalue/resnull ... */
724 scratch.opcode = EEOP_CONST;
725 scratch.resvalue = &state->resvalue;
726 scratch.resnull = &state->resnull;
727 scratch.d.constval.value = (Datum) 0;
728 scratch.d.constval.isnull = true;
730 /* ... then assign it to the result slot */
731 scratch.opcode = EEOP_ASSIGN_TMP;
732 scratch.d.assign_tmp.resultnum = attnum - 1;
734 }
736 {
737 /* Certainly the right type, so needn't check */
739 scratch.d.assign_var.attnum = attnum - 1;
740 scratch.d.assign_var.resultnum = attnum - 1;
742 }
743 }
744
747
749
750 return projInfo;
751}
static void ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info)
Definition execExpr.c:2892
static bool expr_setup_walker(Node *node, ExprSetupInfo *info)
Definition execExpr.c:2978
@ EEOP_CONST
Definition execExpr.h:115
char * format_type_be(Oid type_oid)
bool attisdropped
Definition tupdesc.h:77
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:175

References Assert, CompactAttribute::attisdropped, attnum, bms_add_member(), bms_is_member(), EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_CONST, EEOP_DONE_NO_RETURN, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecInitExprRec(), ExecPushExprSetupSteps(), ExecReadyExpr(), expr_setup_walker(), ExprEvalPushStep(), exprType(), fb(), forboth, format_type_be(), lfirst_int, lfirst_node, list_length(), makeNode, NIL, TupleDescAttr(), TupleDescCompactAttr(), and ExprContext::type.

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)
extern

Definition at line 872 of file execExpr.c.

873{
874 Datum ret;
875 bool isnull;
876
877 /* short-circuit (here and in ExecInitCheck) for empty restriction list */
878 if (state == NULL)
879 return true;
880
881 /* verify that expression was not compiled using ExecInitQual */
882 Assert(!(state->flags & EEO_FLAG_IS_QUAL));
883
884 ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
885
886 if (isnull)
887 return true;
888
889 return DatumGetBool(ret);
890}
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:436
static bool DatumGetBool(Datum X)
Definition postgres.h:100

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

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

◆ ExecCheckIndexConstraints()

bool ExecCheckIndexConstraints ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate,
ItemPointer  conflictTid,
const ItemPointerData tupleid,
List arbiterIndexes 
)
extern

Definition at line 543 of file execIndexing.c.

546{
547 int i;
548 int numIndices;
550 Relation heapRelation;
552 ExprContext *econtext;
554 bool isnull[INDEX_MAX_KEYS];
556 bool checkedIndex = false;
557
560
561 /*
562 * Get information from the result relation info structure.
563 */
564 numIndices = resultRelInfo->ri_NumIndices;
565 relationDescs = resultRelInfo->ri_IndexRelationDescs;
566 indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
567 heapRelation = resultRelInfo->ri_RelationDesc;
568
569 /*
570 * We will use the EState's per-tuple context for evaluating predicates
571 * and index expressions (creating it if it's not already there).
572 */
573 econtext = GetPerTupleExprContext(estate);
574
575 /* Arrange for econtext's scan tuple to be the tuple under test */
576 econtext->ecxt_scantuple = slot;
577
578 /*
579 * For each index, form index tuple and check if it satisfies the
580 * constraint.
581 */
582 for (i = 0; i < numIndices; i++)
583 {
584 Relation indexRelation = relationDescs[i];
585 IndexInfo *indexInfo;
587
588 if (indexRelation == NULL)
589 continue;
590
591 indexInfo = indexInfoArray[i];
592
593 if (!indexInfo->ii_Unique && !indexInfo->ii_ExclusionOps)
594 continue;
595
596 /* If the index is marked as read-only, ignore it */
597 if (!indexInfo->ii_ReadyForInserts)
598 continue;
599
600 /* When specific arbiter indexes requested, only examine them */
601 if (arbiterIndexes != NIL &&
602 !list_member_oid(arbiterIndexes,
603 indexRelation->rd_index->indexrelid))
604 continue;
605
606 if (!indexRelation->rd_index->indimmediate)
609 errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),
610 errtableconstraint(heapRelation,
611 RelationGetRelationName(indexRelation))));
612
613 checkedIndex = true;
614
615 /* Check for partial index */
616 if (indexInfo->ii_Predicate != NIL)
617 {
619
620 /*
621 * If predicate state not set up yet, create it (in the estate's
622 * per-query context)
623 */
624 predicate = indexInfo->ii_PredicateState;
625 if (predicate == NULL)
626 {
627 predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
628 indexInfo->ii_PredicateState = predicate;
629 }
630
631 /* Skip this index-update if the predicate isn't satisfied */
632 if (!ExecQual(predicate, econtext))
633 continue;
634 }
635
636 /*
637 * FormIndexDatum fills in its values and isnull parameters with the
638 * appropriate values for the column(s) of the index.
639 */
640 FormIndexDatum(indexInfo,
641 slot,
642 estate,
643 values,
644 isnull);
645
647 check_exclusion_or_unique_constraint(heapRelation, indexRelation,
648 indexInfo, tupleid,
649 values, isnull, estate, false,
650 CEOUC_WAIT, true,
653 return false;
654 }
655
656 if (arbiterIndexes != NIL && !checkedIndex)
657 elog(ERROR, "unexpected failure to find arbiter index");
658
659 return true;
660}
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition execExpr.c:793
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition executor.h:519
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition index.c:2728
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:6098
bool ii_Unique
Definition execnodes.h:202
ExprState * ii_PredicateState
Definition execnodes.h:187
Oid * ii_ExclusionOps
Definition execnodes.h:190
bool ii_ReadyForInserts
Definition execnodes.h:206
List * ii_Predicate
Definition execnodes.h:185
Form_pg_index rd_index
Definition rel.h:192
RelationPtr ri_IndexRelationDescs
Definition execnodes.h:488
IndexInfo ** ri_IndexRelationInfo
Definition execnodes.h:491

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), ExprContext::ecxt_scantuple, elog, ereport, errcode(), errmsg(), ERROR, errtableconstraint(), ExecPrepareQual(), ExecQual(), fb(), 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(), and FindConflictTuple().

◆ ExecCheckOneRelPerms()

bool ExecCheckOneRelPerms ( RTEPermissionInfo perminfo)
extern

Definition at line 646 of file execMain.c.

647{
648 AclMode requiredPerms;
651 Oid userid;
652 Oid relOid = perminfo->relid;
653
654 requiredPerms = perminfo->requiredPerms;
655 Assert(requiredPerms != 0);
656
657 /*
658 * userid to check as: current user unless we have a setuid indication.
659 *
660 * Note: GetUserId() is presently fast enough that there's no harm in
661 * calling it separately for each relation. If that stops being true, we
662 * could call it once in ExecCheckPermissions and pass the userid down
663 * from there. But for now, no need for the extra clutter.
664 */
665 userid = OidIsValid(perminfo->checkAsUser) ?
666 perminfo->checkAsUser : GetUserId();
667
668 /*
669 * We must have *all* the requiredPerms bits, but some of the bits can be
670 * satisfied from column-level rather than relation-level permissions.
671 * First, remove any bits that are satisfied by relation permissions.
672 */
673 relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL);
674 remainingPerms = requiredPerms & ~relPerms;
675 if (remainingPerms != 0)
676 {
677 int col = -1;
678
679 /*
680 * If we lack any permissions that exist only as relation permissions,
681 * we can fail straight away.
682 */
684 return false;
685
686 /*
687 * Check to see if we have the needed privileges at column level.
688 *
689 * Note: failures just report a table-level error; it would be nicer
690 * to report a column-level error if we have some but not all of the
691 * column privileges.
692 */
694 {
695 /*
696 * When the query doesn't explicitly reference any columns (for
697 * example, SELECT COUNT(*) FROM table), allow the query if we
698 * have SELECT on any column of the rel, as per SQL spec.
699 */
700 if (bms_is_empty(perminfo->selectedCols))
701 {
702 if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
704 return false;
705 }
706
707 while ((col = bms_next_member(perminfo->selectedCols, col)) >= 0)
708 {
709 /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
711
712 if (attno == InvalidAttrNumber)
713 {
714 /* Whole-row reference, must have priv on all cols */
715 if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
717 return false;
718 }
719 else
720 {
721 if (pg_attribute_aclcheck(relOid, attno, userid,
723 return false;
724 }
725 }
726 }
727
728 /*
729 * Basically the same for the mod columns, for both INSERT and UPDATE
730 * privilege as specified by remainingPerms.
731 */
734 userid,
735 perminfo->insertedCols,
736 ACL_INSERT))
737 return false;
738
741 userid,
742 perminfo->updatedCols,
743 ACL_UPDATE))
744 return false;
745 }
746 return true;
747}
@ ACLMASK_ANY
Definition acl.h:177
@ ACLMASK_ALL
Definition acl.h:176
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition aclchk.c:3910
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition aclchk.c:3272
#define InvalidAttrNumber
Definition attnum.h:23
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1305
#define bms_is_empty(a)
Definition bitmapset.h:118
static bool ExecCheckPermissionsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms)
Definition execMain.c:755
uint64 AclMode
Definition parsenodes.h:74
#define ACL_INSERT
Definition parsenodes.h:76
#define ACL_UPDATE
Definition parsenodes.h:78

References ACL_INSERT, ACL_SELECT, ACL_UPDATE, ACLCHECK_OK, ACLMASK_ALL, ACLMASK_ANY, Assert, bms_is_empty, bms_next_member(), ExecCheckPermissionsModified(), fb(), FirstLowInvalidHeapAttributeNumber, GetUserId(), InvalidAttrNumber, OidIsValid, pg_attribute_aclcheck(), pg_attribute_aclcheck_all(), and pg_class_aclmask().

Referenced by ExecCheckPermissions(), and subquery_planner().

◆ ExecCheckPermissions()

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

Definition at line 582 of file execMain.c.

584{
585 ListCell *l;
586 bool result = true;
587
588#ifdef USE_ASSERT_CHECKING
590
591 /* Check that rteperminfos is consistent with rangeTable */
592 foreach(l, rangeTable)
593 {
595
596 if (rte->perminfoindex != 0)
597 {
598 /* Sanity checks */
599
600 /*
601 * Only relation RTEs and subquery RTEs that were once relation
602 * RTEs (views) have their perminfoindex set.
603 */
604 Assert(rte->rtekind == RTE_RELATION ||
605 (rte->rtekind == RTE_SUBQUERY &&
606 rte->relkind == RELKIND_VIEW));
607
608 (void) getRTEPermissionInfo(rteperminfos, rte);
609 /* Many-to-one mapping not allowed */
610 Assert(!bms_is_member(rte->perminfoindex, indexset));
611 indexset = bms_add_member(indexset, rte->perminfoindex);
612 }
613 }
614
615 /* All rteperminfos are referenced */
616 Assert(bms_num_members(indexset) == list_length(rteperminfos));
617#endif
618
619 foreach(l, rteperminfos)
620 {
622
623 Assert(OidIsValid(perminfo->relid));
625 if (!result)
626 {
627 if (ereport_on_violation)
630 get_rel_name(perminfo->relid));
631 return false;
632 }
633 }
634
636 result = (*ExecutorCheckPerms_hook) (rangeTable, rteperminfos,
637 ereport_on_violation);
638 return result;
639}
@ ACLCHECK_NO_PRIV
Definition acl.h:184
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:750
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition execMain.c:74
bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
Definition execMain.c:646
char * get_rel_name(Oid relid)
Definition lsyscache.c:2078
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2153
ObjectType get_relkind_objtype(char relkind)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_SUBQUERY
@ RTE_RELATION

References aclcheck_error(), ACLCHECK_NO_PRIV, Assert, bms_add_member(), bms_is_member(), bms_num_members(), ExecCheckOneRelPerms(), ExecutorCheckPerms_hook, fb(), get_rel_name(), get_rel_relkind(), get_relkind_objtype(), getRTEPermissionInfo(), lfirst_node, list_length(), OidIsValid, RTE_RELATION, and RTE_SUBQUERY.

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)
extern

Definition at line 1185 of file execUtils.c.

1186{
1187 int len = 0;
1188 ListCell *tl;
1189
1190 foreach(tl, targetlist)
1191 {
1193
1194 if (!curTle->resjunk)
1195 len++;
1196 }
1197 return len;
1198}

References fb(), len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)
extern

Definition at line 2139 of file execTuples.c.

2140{
2141 return ExecTypeFromTLInternal(targetList, true);
2142}
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)

References ExecTypeFromTLInternal().

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)
extern

Definition at line 239 of file execIndexing.c.

240{
241 int i;
242 int numIndices;
245
246 numIndices = resultRelInfo->ri_NumIndices;
247 indexDescs = resultRelInfo->ri_IndexRelationDescs;
248 indexInfos = resultRelInfo->ri_IndexRelationInfo;
249
250 for (i = 0; i < numIndices; i++)
251 {
252 /* This Assert will fail if ExecCloseIndices is called twice */
253 Assert(indexDescs[i] != NULL);
254
255 /* Give the index a chance to do some post-insert cleanup */
257
258 /* Drop lock acquired by ExecOpenIndices */
260
261 /* Mark the index as closed */
262 indexDescs[i] = NULL;
263 }
264
265 /*
266 * We don't attempt to free the IndexInfo data structures or the arrays,
267 * instead assuming that such stuff will be cleaned up automatically in
268 * FreeExecutorState.
269 */
270}
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 Assert, fb(), i, index_close(), index_insert_cleanup(), ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, and RowExclusiveLock.

Referenced by apply_handle_delete(), apply_handle_insert(), apply_handle_update_internal(), CatalogCloseIndexes(), ExecCleanupTupleRouting(), and ExecCloseResultRelations().

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)
extern

Definition at line 1639 of file execMain.c.

1640{
1641 int i;
1642
1643 for (i = 0; i < estate->es_range_table_size; i++)
1644 {
1645 if (estate->es_relations[i])
1646 table_close(estate->es_relations[i], NoLock);
1647 }
1648}
#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)
extern

Definition at line 1579 of file execMain.c.

1580{
1581 ListCell *l;
1582
1583 /*
1584 * close indexes of result relation(s) if any. (Rels themselves are
1585 * closed in ExecCloseRangeTableRelations())
1586 *
1587 * In addition, close the stub RTs that may be in each resultrel's
1588 * ri_ancestorResultRels.
1589 */
1590 foreach(l, estate->es_opened_result_relations)
1591 {
1592 ResultRelInfo *resultRelInfo = lfirst(l);
1593 ListCell *lc;
1594
1595 ExecCloseIndices(resultRelInfo);
1596 foreach(lc, resultRelInfo->ri_ancestorResultRels)
1597 {
1599
1600 /*
1601 * Ancestors with RTI > 0 (should only be the root ancestor) are
1602 * closed by ExecCloseRangeTableRelations.
1603 */
1604 if (rInfo->ri_RangeTableIndex > 0)
1605 continue;
1606
1607 table_close(rInfo->ri_RelationDesc, NoLock);
1608 }
1609 }
1610
1611 /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
1612 foreach(l, estate->es_trig_target_relations)
1613 {
1614 ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1615
1616 /*
1617 * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
1618 * might be issuing a duplicate close against a Relation opened by
1619 * ExecGetRangeTableRelation.
1620 */
1621 Assert(resultRelInfo->ri_RangeTableIndex == 0);
1622
1623 /*
1624 * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
1625 * these rels, we needn't call ExecCloseIndices either.
1626 */
1627 Assert(resultRelInfo->ri_NumIndices == 0);
1628
1629 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1630 }
1631}
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Index ri_RangeTableIndex
Definition execnodes.h:479
List * ri_ancestorResultRels
Definition execnodes.h:630

References Assert, EState::es_opened_result_relations, EState::es_trig_target_relations, ExecCloseIndices(), fb(), 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 
)
extern

Definition at line 603 of file execUtils.c.

605{
606 if (tlist_matches_tupdesc(planstate,
607 planstate->plan->targetlist,
608 varno,
609 inputDesc))
610 {
611 planstate->ps_ProjInfo = NULL;
612 planstate->resultopsset = planstate->scanopsset;
613 planstate->resultopsfixed = planstate->scanopsfixed;
614 planstate->resultops = planstate->scanops;
615 }
616 else
617 {
618 if (!planstate->ps_ResultTupleSlot)
619 {
621 planstate->resultops = &TTSOpsVirtual;
622 planstate->resultopsfixed = true;
623 planstate->resultopsset = true;
624 }
626 }
627}
const TupleTableSlotOps TTSOpsVirtual
Definition execTuples.c:84
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
Definition execUtils.c:630
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition execUtils.c:583
const TupleTableSlotOps * resultops
Definition execnodes.h:1244
bool resultopsset
Definition execnodes.h:1252
const TupleTableSlotOps * scanops
Definition execnodes.h:1241
bool scanopsset
Definition execnodes.h:1249
bool scanopsfixed
Definition execnodes.h:1245
bool resultopsfixed
Definition execnodes.h:1248

References ExecAssignProjectionInfo(), ExecInitResultSlot(), fb(), 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 
)
extern

Definition at line 1984 of file execMain.c.

1986{
1987 Relation rel = resultRelInfo->ri_RelationDesc;
1988 TupleDesc tupdesc = RelationGetDescr(rel);
1989 TupleConstr *constr = tupdesc->constr;
1992
1993 Assert(constr); /* we should not be called otherwise */
1994
1995 /*
1996 * Verify not-null constraints.
1997 *
1998 * Not-null constraints on virtual generated columns are collected and
1999 * checked separately below.
2000 */
2001 if (constr->has_not_null)
2002 {
2003 for (AttrNumber attnum = 1; attnum <= tupdesc->natts; attnum++)
2004 {
2005 Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2006
2007 if (att->attnotnull && att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
2009 else if (att->attnotnull && slot_attisnull(slot, attnum))
2010 ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
2011 }
2012 }
2013
2014 /*
2015 * Verify not-null constraints on virtual generated column, if any.
2016 */
2018 {
2020
2021 attnum = ExecRelGenVirtualNotNull(resultRelInfo, slot, estate,
2024 ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
2025 }
2026
2027 /*
2028 * Verify check constraints.
2029 */
2030 if (rel->rd_rel->relchecks > 0)
2031 {
2032 const char *failed;
2033
2034 if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2035 {
2036 char *val_desc;
2037 Relation orig_rel = rel;
2038
2039 /*
2040 * If the tuple has been routed, it's been converted to the
2041 * partition's rowtype, which might differ from the root table's.
2042 * We must convert it back to the root table's rowtype so that
2043 * val_desc shown error message matches the input tuple.
2044 */
2045 if (resultRelInfo->ri_RootResultRelInfo)
2046 {
2047 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2049 AttrMap *map;
2050
2051 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2052 /* a reverse map */
2054 tupdesc,
2055 false);
2056
2057 /*
2058 * Partition-specific slot's tupdesc can't be changed, so
2059 * allocate a new one.
2060 */
2061 if (map != NULL)
2062 slot = execute_attr_map_slot(map, slot,
2065 ExecGetUpdatedCols(rootrel, estate));
2066 rel = rootrel->ri_RelationDesc;
2067 }
2068 else
2069 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2070 ExecGetUpdatedCols(resultRelInfo, estate));
2072 slot,
2073 tupdesc,
2075 64);
2076 ereport(ERROR,
2078 errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2080 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2081 errtableconstraint(orig_rel, failed)));
2082 }
2083 }
2084}
AttrMap * build_attrmap_by_name_if_req(TupleDesc indesc, TupleDesc outdesc, bool missing_ok)
Definition attmap.c:261
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
static void ReportNotNullViolationError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, int attnum)
Definition execMain.c:2163
char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition execMain.c:2395
AttrNumber ExecRelGenVirtualNotNull(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, List *notnull_virtual_attrs)
Definition execMain.c:2098
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition execMain.c:1782
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1361
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1382
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
struct ResultRelInfo * ri_RootResultRelInfo
Definition execnodes.h:620
bool has_not_null
Definition tupdesc.h:45
TupleConstr * constr
Definition tupdesc.h:141
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition tupconvert.c:193
static bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition tuptable.h:384

References Assert, attnum, bms_union(), build_attrmap_by_name_if_req(), TupleDescData::constr, ereport, errcode(), errdetail(), errmsg(), ERROR, errtableconstraint(), ExecBuildSlotValueDescription(), ExecGetInsertedCols(), ExecGetUpdatedCols(), ExecRelCheck(), ExecRelGenVirtualNotNull(), execute_attr_map_slot(), fb(), TupleConstr::has_not_null, InvalidAttrNumber, lappend_int(), MakeTupleTableSlot(), TupleDescData::natts, NIL, RelationData::rd_rel, RelationGetDescr, RelationGetRelationName, RelationGetRelid, ReportNotNullViolationError(), 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 
)
extern

Definition at line 704 of file execUtils.c.

707{
709 TupleDesc tupDesc;
710
712 tupDesc = ExecGetResultType(outerPlan);
713
714 ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
715}
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
TupleDesc ExecGetResultType(PlanState *planstate)
Definition execUtils.c:495
#define outerPlanState(node)
Definition execnodes.h:1263
#define outerPlan(node)
Definition plannodes.h:261

References ExecGetResultType(), ExecInitScanTupleSlot(), fb(), 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 
)
extern

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))
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)
79 errmsg("cursor \"%s\" is not a SELECT query",
80 cursor_name)));
81 queryDesc = portal->queryDesc;
82 if (queryDesc == NULL || queryDesc->estate == NULL)
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 {
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)
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)
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)
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 */
162 bool pending_rescan = false;
163
166 if (!scanstate)
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)
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 */
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_heaptid.
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;
220
221#ifdef USE_ASSERT_CHECKING
222 ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
224 &lisnull);
225 if (lisnull)
228 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
229 cursor_name, table_name)));
231#endif
232
233 ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
235 &lisnull);
236 if (lisnull)
239 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
240 cursor_name, table_name)));
242
244 }
245
247
248 return true;
249 }
250}
static ScanState * search_plan_tree(PlanState *node, Oid table_oid, bool *pending_rescan)
static char * fetch_cursor_param_value(ExprContext *econtext, int paramId)
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:211
Portal GetPortalByName(const char *name)
Definition portalmem.c:130
char * cursor_name
Definition primnodes.h:2123
ItemPointerData xs_heaptid
Definition relscan.h:173
QueryDesc * queryDesc
Definition portal.h:156
bool atEnd
Definition portal.h:199
bool atStart
Definition portal.h:198
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:419

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

Referenced by TidListEval().

◆ ExecEndNode()

void ExecEndNode ( PlanState node)
extern

Definition at line 562 of file execProcnode.c.

563{
564 /*
565 * do nothing when we get to the end of a leaf on tree.
566 */
567 if (node == NULL)
568 return;
569
570 /*
571 * Make sure there's enough stack available. Need to check here, in
572 * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
573 * guaranteed that ExecProcNode() is reached for all nodes.
574 */
576
577 if (node->chgParam != NULL)
578 {
579 bms_free(node->chgParam);
580 node->chgParam = NULL;
581 }
582
583 switch (nodeTag(node))
584 {
585 /*
586 * control nodes
587 */
588 case T_ResultState:
589 ExecEndResult((ResultState *) node);
590 break;
591
594 break;
595
598 break;
599
600 case T_AppendState:
601 ExecEndAppend((AppendState *) node);
602 break;
603
606 break;
607
610 break;
611
612 case T_BitmapAndState:
614 break;
615
616 case T_BitmapOrState:
618 break;
619
620 /*
621 * scan nodes
622 */
623 case T_SeqScanState:
625 break;
626
629 break;
630
631 case T_GatherState:
632 ExecEndGather((GatherState *) node);
633 break;
634
637 break;
638
639 case T_IndexScanState:
641 break;
642
645 break;
646
649 break;
650
653 break;
654
655 case T_TidScanState:
657 break;
658
661 break;
662
665 break;
666
669 break;
670
673 break;
674
675 case T_CteScanState:
677 break;
678
681 break;
682
685 break;
686
687 /*
688 * join nodes
689 */
690 case T_NestLoopState:
692 break;
693
694 case T_MergeJoinState:
696 break;
697
698 case T_HashJoinState:
700 break;
701
702 /*
703 * materialization nodes
704 */
705 case T_MaterialState:
707 break;
708
709 case T_SortState:
710 ExecEndSort((SortState *) node);
711 break;
712
715 break;
716
717 case T_MemoizeState:
719 break;
720
721 case T_GroupState:
722 ExecEndGroup((GroupState *) node);
723 break;
724
725 case T_AggState:
726 ExecEndAgg((AggState *) node);
727 break;
728
729 case T_WindowAggState:
731 break;
732
733 case T_UniqueState:
734 ExecEndUnique((UniqueState *) node);
735 break;
736
737 case T_HashState:
738 ExecEndHash((HashState *) node);
739 break;
740
741 case T_SetOpState:
742 ExecEndSetOp((SetOpState *) node);
743 break;
744
745 case T_LockRowsState:
747 break;
748
749 case T_LimitState:
750 ExecEndLimit((LimitState *) node);
751 break;
752
753 /* No clean up actions for these nodes. */
757 break;
758
759 default:
760 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
761 break;
762 }
763}
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
void ExecEndAgg(AggState *node)
Definition nodeAgg.c:4394
void ExecEndAppend(AppendState *node)
Definition nodeAppend.c:401
void ExecEndBitmapAnd(BitmapAndState *node)
void ExecEndBitmapHeapScan(BitmapHeapScanState *node)
void ExecEndBitmapIndexScan(BitmapIndexScanState *node)
void ExecEndBitmapOr(BitmapOrState *node)
void ExecEndCteScan(CteScanState *node)
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:251
void ExecEndGroup(GroupState *node)
Definition nodeGroup.c:226
void ExecEndHash(HashState *node)
Definition nodeHash.c:426
void ExecEndHashJoin(HashJoinState *node)
void ExecEndIncrementalSort(IncrementalSortState *node)
void ExecEndIndexOnlyScan(IndexOnlyScanState *node)
void ExecEndIndexScan(IndexScanState *node)
void ExecEndLimit(LimitState *node)
Definition nodeLimit.c:534
void ExecEndLockRows(LockRowsState *node)
void ExecEndMaterial(MaterialState *node)
void ExecEndMemoize(MemoizeState *node)
void ExecEndMergeAppend(MergeAppendState *node)
void ExecEndMergeJoin(MergeJoinState *node)
void ExecEndModifyTable(ModifyTableState *node)
void ExecEndNestLoop(NestLoopState *node)
void ExecEndProjectSet(ProjectSetState *node)
void ExecEndRecursiveUnion(RecursiveUnionState *node)
void ExecEndResult(ResultState *node)
Definition nodeResult.c:240
void ExecEndSampleScan(SampleScanState *node)
void ExecEndSeqScan(SeqScanState *node)
void ExecEndSetOp(SetOpState *node)
Definition nodeSetOp.c:691
void ExecEndSort(SortState *node)
Definition nodeSort.c:301
void ExecEndSubqueryScan(SubqueryScanState *node)
void ExecEndTableFuncScan(TableFuncScanState *node)
void ExecEndTidRangeScan(TidRangeScanState *node)
void ExecEndTidScan(TidScanState *node)
void ExecEndUnique(UniqueState *node)
Definition nodeUnique.c:168
void ExecEndWindowAgg(WindowAggState *node)
#define nodeTag(nodeptr)
Definition nodes.h:139
void check_stack_depth(void)
Definition stack_depth.c:95
Bitmapset * chgParam
Definition execnodes.h:1199

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(), fb(), 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()

◆ ExecEvalExprNoReturn()

static void ExecEvalExprNoReturn ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 418 of file executor.h.

420{
422
423 retDatum = state->evalfunc(state, econtext, NULL);
424
425 Assert(retDatum == (Datum) 0);
426}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:223

References Assert, fb(), and PG_USED_FOR_ASSERTS_ONLY.

Referenced by ExecEvalExprNoReturnSwitchContext().

◆ ExecEvalExprNoReturnSwitchContext()

static void ExecEvalExprNoReturnSwitchContext ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 458 of file executor.h.

460{
462
464 ExecEvalExprNoReturn(state, econtext);
466}
static void ExecEvalExprNoReturn(ExprState *state, ExprContext *econtext)
Definition executor.h:418

References ExprContext::ecxt_per_tuple_memory, ExecEvalExprNoReturn(), fb(), and MemoryContextSwitchTo().

Referenced by advance_aggregates(), and ExecProject().

◆ ExecEvalExprSwitchContext()

◆ ExecFilterJunk()

TupleTableSlot * ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)
extern

Definition at line 247 of file execJunk.c.

248{
252 int cleanLength;
253 int i;
254 Datum *values;
255 bool *isnull;
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 */
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 */
304}
int j
Definition isn.c:78

References ExecClearTuple(), ExecStoreVirtualTuple(), fb(), i, j, 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 
)
extern

Definition at line 210 of file execJunk.c.

211{
212 return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
213}

References ExecFindJunkAttributeInTlist(), and fb().

◆ ExecFindJunkAttributeInTlist()

AttrNumber ExecFindJunkAttributeInTlist ( List targetlist,
const char attrName 
)
extern

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}

References fb(), InvalidAttrNumber, and lfirst.

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

◆ ExecFindRowMark()

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

Definition at line 2560 of file execMain.c.

2561{
2562 if (rti > 0 && rti <= estate->es_range_table_size &&
2563 estate->es_rowmarks != NULL)
2564 {
2565 ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2566
2567 if (erm)
2568 return erm;
2569 }
2570 if (!missing_ok)
2571 elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2572 return NULL;
2573}

References elog, ERROR, EState::es_rowmarks, and fb().

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecGetAllNullSlot()

TupleTableSlot * ExecGetAllNullSlot ( EState estate,
ResultRelInfo relInfo 
)
extern

Definition at line 1273 of file execUtils.c.

1274{
1275 if (relInfo->ri_AllNullSlot == NULL)
1276 {
1277 Relation rel = relInfo->ri_RelationDesc;
1278 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1279 TupleTableSlot *slot;
1280
1281 slot = ExecInitExtraTupleSlot(estate,
1282 RelationGetDescr(rel),
1285
1286 relInfo->ri_AllNullSlot = slot;
1287
1288 MemoryContextSwitchTo(oldcontext);
1289 }
1290
1291 return relInfo->ri_AllNullSlot;
1292}
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition tableam.c:59

References EState::es_query_cxt, ExecInitExtraTupleSlot(), ExecStoreAllNullTuple(), fb(), MemoryContextSwitchTo(), RelationGetDescr, and table_slot_callbacks().

Referenced by ExecProcessReturning().

◆ ExecGetAllUpdatedCols()

Bitmapset * ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)
extern

Definition at line 1418 of file execUtils.c.

1419{
1420 Bitmapset *ret;
1422
1424
1425 ret = bms_union(ExecGetUpdatedCols(relinfo, estate),
1427
1429
1430 return ret;
1431}
Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1403
#define GetPerTupleMemoryContext(estate)
Definition executor.h:661

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

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

◆ ExecGetAncestorResultRels()

List * ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)
extern

Definition at line 1434 of file execMain.c.

1435{
1437 Relation partRel = resultRelInfo->ri_RelationDesc;
1439
1440 if (!partRel->rd_rel->relispartition)
1441 elog(ERROR, "cannot find ancestors of a non-partition result relation");
1443 rootRelOid = RelationGetRelid(rootRelInfo->ri_RelationDesc);
1444 if (resultRelInfo->ri_ancestorResultRels == NIL)
1445 {
1446 ListCell *lc;
1449
1450 foreach(lc, oids)
1451 {
1455
1456 /*
1457 * Ignore the root ancestor here, and use ri_RootResultRelInfo
1458 * (below) for it instead. Also, we stop climbing up the
1459 * hierarchy when we find the table that was mentioned in the
1460 * query.
1461 */
1462 if (ancOid == rootRelOid)
1463 break;
1464
1465 /*
1466 * All ancestors up to the root target relation must have been
1467 * locked by the planner or AcquireExecutorLocks().
1468 */
1471
1472 /* dummy rangetable index */
1474 estate->es_instrument);
1476 }
1478 resultRelInfo->ri_ancestorResultRels = ancResultRels;
1479 }
1480
1481 /* We must have found some ancestor */
1482 Assert(resultRelInfo->ri_ancestorResultRels != NIL);
1483
1484 return resultRelInfo->ri_ancestorResultRels;
1485}
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
Definition execMain.c:1247
List * lappend(List *list, void *datum)
Definition list.c:339
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40

References Assert, elog, ERROR, EState::es_instrument, fb(), 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)
extern

Definition at line 1300 of file execUtils.c.

1301{
1302 /* If we didn't already do so, compute the map for this child. */
1303 if (!resultRelInfo->ri_ChildToRootMapValid)
1304 {
1306
1307 if (rootRelInfo)
1308 resultRelInfo->ri_ChildToRootMap =
1310 RelationGetDescr(rootRelInfo->ri_RelationDesc));
1311 else /* this isn't a child result rel */
1312 resultRelInfo->ri_ChildToRootMap = NULL;
1313
1314 resultRelInfo->ri_ChildToRootMapValid = true;
1315 }
1316
1317 return resultRelInfo->ri_ChildToRootMap;
1318}
TupleConversionMap * ri_ChildToRootMap
Definition execnodes.h:602
bool ri_ChildToRootMapValid
Definition execnodes.h:603
TupleConversionMap * convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc)
Definition tupconvert.c:103

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

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

◆ ExecGetCommonChildSlotOps()

const TupleTableSlotOps * ExecGetCommonChildSlotOps ( PlanState ps)
extern

Definition at line 563 of file execUtils.c.

564{
566
570}
const TupleTableSlotOps * ExecGetCommonSlotOps(PlanState **planstates, int nplans)
Definition execUtils.c:536
#define innerPlanState(node)
Definition execnodes.h:1262
struct parser_state ps

References ExecGetCommonSlotOps(), fb(), innerPlanState, outerPlanState, and ps.

Referenced by build_hash_table(), and build_hash_table().

◆ ExecGetCommonSlotOps()

const TupleTableSlotOps * ExecGetCommonSlotOps ( PlanState **  planstates,
int  nplans 
)
extern

Definition at line 536 of file execUtils.c.

537{
538 const TupleTableSlotOps *result;
539 bool isfixed;
540
541 if (nplans <= 0)
542 return NULL;
543 result = ExecGetResultSlotOps(planstates[0], &isfixed);
544 if (!isfixed)
545 return NULL;
546 for (int i = 1; i < nplans; i++)
547 {
549
551 if (!isfixed)
552 return NULL;
553 if (result != thisops)
554 return NULL;
555 }
556 return result;
557}
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition execUtils.c:504

References ExecGetResultSlotOps(), fb(), and i.

Referenced by ExecGetCommonChildSlotOps(), ExecInitAppend(), and ExecInitMergeAppend().

◆ ExecGetExtraUpdatedCols()

Bitmapset * ExecGetExtraUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)
extern

Definition at line 1403 of file execUtils.c.

1404{
1405 /* Compute the info if we didn't already */
1406 if (!relinfo->ri_extraUpdatedCols_valid)
1408 return relinfo->ri_extraUpdatedCols;
1409}
void ExecInitGenerated(ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype)

References CMD_UPDATE, ExecInitGenerated(), and fb().

Referenced by ExecGetAllUpdatedCols(), and index_unchanged_by_update().

◆ ExecGetInsertedCols()

Bitmapset * ExecGetInsertedCols ( ResultRelInfo relinfo,
EState estate 
)
extern

Definition at line 1361 of file execUtils.c.

1362{
1364
1365 if (perminfo == NULL)
1366 return NULL;
1367
1368 /* Map the columns to child's attribute numbers if needed. */
1369 if (relinfo->ri_RootResultRelInfo)
1370 {
1372
1373 if (map)
1374 return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
1375 }
1376
1377 return perminfo->insertedCols;
1378}
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition execUtils.c:1326
static RTEPermissionInfo * GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1438
AttrMap * attrMap
Definition tupconvert.h:28
Bitmapset * execute_attr_map_cols(AttrMap *attrMap, Bitmapset *in_cols)
Definition tupconvert.c:253

References TupleConversionMap::attrMap, ExecGetRootToChildMap(), execute_attr_map_cols(), fb(), and GetResultRTEPermissionInfo().

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

◆ ExecGetJunkAttribute()

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

Definition at line 225 of file executor.h.

226{
227 Assert(attno > 0);
228 return slot_getattr(slot, attno, isNull);
229}
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition tuptable.h:398

References Assert, and slot_getattr().

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

◆ ExecGetRangeTableRelation()

Relation ExecGetRangeTableRelation ( EState estate,
Index  rti,
bool  isResultRel 
)
extern

Definition at line 825 of file execUtils.c.

826{
827 Relation rel;
828
829 Assert(rti > 0 && rti <= estate->es_range_table_size);
830
831 if (!isResultRel && !bms_is_member(rti, estate->es_unpruned_relids))
832 elog(ERROR, "trying to open a pruned relation");
833
834 rel = estate->es_relations[rti - 1];
835 if (rel == NULL)
836 {
837 /* First time through, so open the relation */
838 RangeTblEntry *rte = exec_rt_fetch(rti, estate);
839
840 Assert(rte->rtekind == RTE_RELATION);
841
842 if (!IsParallelWorker())
843 {
844 /*
845 * In a normal query, we should already have the appropriate lock,
846 * but verify that through an Assert. Since there's already an
847 * Assert inside table_open that insists on holding some lock, it
848 * seems sufficient to check this only when rellockmode is higher
849 * than the minimum.
850 */
851 rel = table_open(rte->relid, NoLock);
852 Assert(rte->rellockmode == AccessShareLock ||
853 CheckRelationLockedByMe(rel, rte->rellockmode, false));
854 }
855 else
856 {
857 /*
858 * If we are a parallel worker, we need to obtain our own local
859 * lock on the relation. This ensures sane behavior in case the
860 * parent process exits before we do.
861 */
862 rel = table_open(rte->relid, rte->rellockmode);
863 }
864
865 estate->es_relations[rti - 1] = rel;
866 }
867
868 return rel;
869}
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition executor.h:697
#define IsParallelWorker()
Definition parallel.h:60
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition lmgr.c:334
#define AccessShareLock
Definition lockdefs.h:36
Bitmapset * es_unpruned_relids
Definition execnodes.h:675

References AccessShareLock, Assert, bms_is_member(), CheckRelationLockedByMe(), elog, ERROR, EState::es_relations, EState::es_unpruned_relids, exec_rt_fetch(), fb(), IsParallelWorker, NoLock, RTE_RELATION, and table_open().

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

◆ ExecGetResultRelCheckAsUser()

Oid ExecGetResultRelCheckAsUser ( ResultRelInfo relInfo,
EState estate 
)
extern

Definition at line 1489 of file execUtils.c.

1490{
1492
1493 /* XXX - maybe ok to return GetUserId() in this case? */
1494 if (perminfo == NULL)
1495 elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
1496 RelationGetRelid(relInfo->ri_RelationDesc));
1497
1498 return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
1499}

References elog, ERROR, fb(), GetResultRTEPermissionInfo(), GetUserId(), and RelationGetRelid.

Referenced by create_foreign_modify().

◆ ExecGetResultSlotOps()

const TupleTableSlotOps * ExecGetResultSlotOps ( PlanState planstate,
bool isfixed 
)
extern

Definition at line 504 of file execUtils.c.

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

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

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

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot * ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)
extern

Definition at line 1248 of file execUtils.c.

1249{
1250 if (relInfo->ri_ReturningSlot == NULL)
1251 {
1252 Relation rel = relInfo->ri_RelationDesc;
1253 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1254
1255 relInfo->ri_ReturningSlot =
1257 RelationGetDescr(rel),
1259
1260 MemoryContextSwitchTo(oldcontext);
1261 }
1262
1263 return relInfo->ri_ReturningSlot;
1264}

References EState::es_query_cxt, ExecInitExtraTupleSlot(), fb(), MemoryContextSwitchTo(), RelationGetDescr, and table_slot_callbacks().

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

◆ ExecGetRootToChildMap()

TupleConversionMap * ExecGetRootToChildMap ( ResultRelInfo resultRelInfo,
EState estate 
)
extern

Definition at line 1326 of file execUtils.c.

1327{
1328 /* Mustn't get called for a non-child result relation. */
1329 Assert(resultRelInfo->ri_RootResultRelInfo);
1330
1331 /* If we didn't already do so, compute the map for this child. */
1332 if (!resultRelInfo->ri_RootToChildMapValid)
1333 {
1335 TupleDesc indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
1336 TupleDesc outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1337 Relation childrel = resultRelInfo->ri_RelationDesc;
1338 AttrMap *attrMap;
1339 MemoryContext oldcontext;
1340
1341 /*
1342 * When this child table is not a partition (!relispartition), it may
1343 * have columns that are not present in the root table, which we ask
1344 * to ignore by passing true for missing_ok.
1345 */
1346 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1347 attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
1348 !childrel->rd_rel->relispartition);
1349 if (attrMap)
1350 resultRelInfo->ri_RootToChildMap =
1351 convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
1352 MemoryContextSwitchTo(oldcontext);
1353 resultRelInfo->ri_RootToChildMapValid = true;
1354 }
1355
1356 return resultRelInfo->ri_RootToChildMap;
1357}
TupleConversionMap * ri_RootToChildMap
Definition execnodes.h:608
bool ri_RootToChildMapValid
Definition execnodes.h:609
TupleConversionMap * convert_tuples_by_name_attrmap(TupleDesc indesc, TupleDesc outdesc, AttrMap *attrMap)
Definition tupconvert.c:125

References Assert, build_attrmap_by_name_if_req(), convert_tuples_by_name_attrmap(), EState::es_query_cxt, fb(), MemoryContextSwitchTo(), 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(), ExecInsert(), and ExecPrepareTupleRouting().

◆ ExecGetTriggerNewSlot()

TupleTableSlot * ExecGetTriggerNewSlot ( EState estate,
ResultRelInfo relInfo 
)
extern

Definition at line 1226 of file execUtils.c.

1227{
1228 if (relInfo->ri_TrigNewSlot == NULL)
1229 {
1230 Relation rel = relInfo->ri_RelationDesc;
1231 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1232
1233 relInfo->ri_TrigNewSlot =
1235 RelationGetDescr(rel),
1237
1238 MemoryContextSwitchTo(oldcontext);
1239 }
1240
1241 return relInfo->ri_TrigNewSlot;
1242}

References EState::es_query_cxt, ExecInitExtraTupleSlot(), fb(), MemoryContextSwitchTo(), RelationGetDescr, and table_slot_callbacks().

Referenced by AfterTriggerExecute(), and AfterTriggerSaveEvent().

◆ ExecGetTriggerOldSlot()

TupleTableSlot * ExecGetTriggerOldSlot ( EState estate,
ResultRelInfo relInfo 
)
extern

Definition at line 1204 of file execUtils.c.

1205{
1206 if (relInfo->ri_TrigOldSlot == NULL)
1207 {
1208 Relation rel = relInfo->ri_RelationDesc;
1209 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1210
1211 relInfo->ri_TrigOldSlot =
1213 RelationGetDescr(rel),
1215
1216 MemoryContextSwitchTo(oldcontext);
1217 }
1218
1219 return relInfo->ri_TrigOldSlot;
1220}

References EState::es_query_cxt, ExecInitExtraTupleSlot(), fb(), MemoryContextSwitchTo(), RelationGetDescr, and table_slot_callbacks().

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

◆ ExecGetTriggerResultRel()

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

Definition at line 1347 of file execMain.c.

1349{
1351 ListCell *l;
1352 Relation rel;
1353 MemoryContext oldcontext;
1354
1355 /*
1356 * Before creating a new ResultRelInfo, check if we've already made and
1357 * cached one for this relation. We must ensure that the given
1358 * 'rootRelInfo' matches the one stored in the cached ResultRelInfo as
1359 * trigger handling for partitions can result in mixed requirements for
1360 * what ri_RootResultRelInfo is set to.
1361 */
1362
1363 /* Search through the query result relations */
1364 foreach(l, estate->es_opened_result_relations)
1365 {
1366 rInfo = lfirst(l);
1367 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid &&
1368 rInfo->ri_RootResultRelInfo == rootRelInfo)
1369 return rInfo;
1370 }
1371
1372 /*
1373 * Search through the result relations that were created during tuple
1374 * routing, if any.
1375 */
1376 foreach(l, estate->es_tuple_routing_result_relations)
1377 {
1378 rInfo = (ResultRelInfo *) lfirst(l);
1379 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid &&
1380 rInfo->ri_RootResultRelInfo == rootRelInfo)
1381 return rInfo;
1382 }
1383
1384 /* Nope, but maybe we already made an extra ResultRelInfo for it */
1385 foreach(l, estate->es_trig_target_relations)
1386 {
1387 rInfo = (ResultRelInfo *) lfirst(l);
1388 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid &&
1389 rInfo->ri_RootResultRelInfo == rootRelInfo)
1390 return rInfo;
1391 }
1392 /* Nope, so we need a new one */
1393
1394 /*
1395 * Open the target relation's relcache entry. We assume that an
1396 * appropriate lock is still held by the backend from whenever the trigger
1397 * event got queued, so we need take no new lock here. Also, we need not
1398 * recheck the relkind, so no need for CheckValidResultRel.
1399 */
1400 rel = table_open(relid, NoLock);
1401
1402 /*
1403 * Make the new entry in the right context.
1404 */
1405 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1408 rel,
1409 0, /* dummy rangetable index */
1411 estate->es_instrument);
1412 estate->es_trig_target_relations =
1414 MemoryContextSwitchTo(oldcontext);
1415
1416 /*
1417 * Currently, we don't need any index information in ResultRelInfos used
1418 * only for triggers, so no need to call ExecOpenIndices.
1419 */
1420
1421 return rInfo;
1422}

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

Referenced by afterTriggerInvokeEvents().

◆ ExecGetUpdatedCols()

Bitmapset * ExecGetUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)
extern

Definition at line 1382 of file execUtils.c.

1383{
1385
1386 if (perminfo == NULL)
1387 return NULL;
1388
1389 /* Map the columns to child's attribute numbers if needed. */
1390 if (relinfo->ri_RootResultRelInfo)
1391 {
1393
1394 if (map)
1395 return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
1396 }
1397
1398 return perminfo->updatedCols;
1399}

References TupleConversionMap::attrMap, ExecGetRootToChildMap(), execute_attr_map_cols(), fb(), and GetResultRTEPermissionInfo().

Referenced by ExecConstraints(), ExecGetAllUpdatedCols(), ExecInitGenerated(), ExecPartitionCheckEmitError(), ExecWithCheckOptions(), get_tuple_desc(), index_unchanged_by_update(), and ReportNotNullViolationError().

◆ ExecGetUpdateNewTuple()

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

Definition at line 813 of file nodeModifyTable.c.

816{
817 ProjectionInfo *newProj = relinfo->ri_projectNew;
818 ExprContext *econtext;
819
820 /* Use a few extra Asserts to protect against outside callers */
821 Assert(relinfo->ri_projectNewInfoValid);
822 Assert(planSlot != NULL && !TTS_EMPTY(planSlot));
824
825 econtext = newProj->pi_exprContext;
826 econtext->ecxt_outertuple = planSlot;
827 econtext->ecxt_scantuple = oldSlot;
828 return ExecProject(newProj);
829}
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition executor.h:483
#define TTS_EMPTY(slot)
Definition tuptable.h:95

References Assert, ExprContext::ecxt_outertuple, ExprContext::ecxt_scantuple, ExecProject(), fb(), and TTS_EMPTY.

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

◆ ExecInitCheck()

ExprState * ExecInitCheck ( List qual,
PlanState parent 
)
extern

Definition at line 315 of file execExpr.c.

316{
317 /* short-circuit (here and in ExecCheck) for empty restriction list */
318 if (qual == NIL)
319 return NULL;
320
321 Assert(IsA(qual, List));
322
323 /*
324 * Just convert the implicit-AND list to an explicit AND (if there's more
325 * than one entry), and compile normally. Unlike ExecQual, we can't
326 * short-circuit on NULL results, so the regular AND behavior is needed.
327 */
328 return ExecInitExpr(make_ands_explicit(qual), parent);
329}
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition execExpr.c:143
Expr * make_ands_explicit(List *andclauses)
Definition makefuncs.c:799

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

Referenced by ExecPrepareCheck().

◆ ExecInitExpr()

ExprState * ExecInitExpr ( Expr node,
PlanState parent 
)
extern

Definition at line 143 of file execExpr.c.

144{
146 ExprEvalStep scratch = {0};
147
148 /* Special case: NULL expression produces a NULL ExprState pointer */
149 if (node == NULL)
150 return NULL;
151
152 /* Initialize ExprState with empty step list */
154 state->expr = node;
155 state->parent = parent;
156 state->ext_params = NULL;
157
158 /* Insert setup steps as needed */
160
161 /* Compile the expression proper */
162 ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
163
164 /* Finally, append a DONE step */
165 scratch.opcode = EEOP_DONE_RETURN;
167
169
170 return state;
171}

References EEOP_DONE_RETURN, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), fb(), and makeNode.

Referenced by ATRewriteTable(), BeginCopyFrom(), buildExpressionExecutionStates(), 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 
)
extern

Definition at line 335 of file execExpr.c.

336{
337 List *result = NIL;
338 ListCell *lc;
339
340 foreach(lc, nodes)
341 {
342 Expr *e = lfirst(lc);
343
344 result = lappend(result, ExecInitExpr(e, parent));
345 }
346
347 return result;
348}
e

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

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

◆ ExecInitExprWithParams()

ExprState * ExecInitExprWithParams ( Expr node,
ParamListInfo  ext_params 
)
extern

Definition at line 180 of file execExpr.c.

181{
183 ExprEvalStep scratch = {0};
184
185 /* Special case: NULL expression produces a NULL ExprState pointer */
186 if (node == NULL)
187 return NULL;
188
189 /* Initialize ExprState with empty step list */
191 state->expr = node;
192 state->parent = NULL;
193 state->ext_params = ext_params;
194
195 /* Insert setup steps as needed */
197
198 /* Compile the expression proper */
199 ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
200
201 /* Finally, append a DONE step */
202 scratch.opcode = EEOP_DONE_RETURN;
204
206
207 return state;
208}

References EEOP_DONE_RETURN, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), fb(), and makeNode.

Referenced by exec_eval_simple_expr(), and InitPartitionPruneContext().

◆ ExecInitExtraTupleSlot()

◆ ExecInitFunctionResultSet()

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

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:335
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
Oid funcid
Definition primnodes.h:782
List * args
Definition primnodes.h:800
List * args
Definition primnodes.h:868

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 
)
extern

Definition at line 60 of file execJunk.c.

61{
64 int cleanLength;
66
67 /*
68 * Compute the tuple descriptor for the cleaned tuple.
69 */
71
72 /*
73 * Use the given slot, or make a new slot if we weren't given one.
74 */
75 if (slot)
77 else
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 */
91 if (cleanLength > 0)
92 {
94 ListCell *t;
95
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 }
109 }
110 else
111 cleanMap = NULL;
112
113 /*
114 * Finally create and initialize the JunkFilter struct.
115 */
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)
void * palloc(Size size)
Definition mcxt.c:1387

References Assert, ExecCleanTypeFromTL(), ExecSetSlotDescriptor(), fb(), lfirst, makeNode, MakeSingleTupleTableSlot(), palloc(), and TTSOpsVirtual.

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

◆ ExecInitJunkFilterConversion()

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

Definition at line 137 of file execJunk.c.

140{
142 int cleanLength;
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)
152 else
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 {
169 t = list_head(targetList);
170 for (i = 0; i < cleanLength; i++)
171 {
172 if (TupleDescCompactAttr(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 */
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(), fb(), i, lfirst, list_head(), lnext(), makeNode, MakeSingleTupleTableSlot(), palloc0(), TTSOpsVirtual, and TupleDescCompactAttr().

Referenced by init_execution_state().

◆ ExecInitNode()

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

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
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
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
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 * The defining characteristic of initplans is that they don't have
398 * arguments, so we don't need to evaluate them (in contrast to
399 * ExecInitSubPlanExpr()).
400 */
401 subps = NIL;
402 foreach(l, node->initPlan)
403 {
404 SubPlan *subplan = (SubPlan *) lfirst(l);
405 SubPlanState *sstate;
406
407 Assert(IsA(subplan, SubPlan));
408 Assert(subplan->args == NIL);
409 sstate = ExecInitSubPlan(subplan, result);
410 subps = lappend(subps, sstate);
411 }
412 result->initPlan = subps;
413
414 /* Set up instrumentation for this node if requested */
415 if (estate->es_instrument)
416 result->instrument = InstrAlloc(1, estate->es_instrument,
417 result->async_capable);
418
419 return result;
420}
void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
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:3279
AppendState * ExecInitAppend(Append *node, EState *estate, int eflags)
Definition nodeAppend.c:109
BitmapAndState * ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
BitmapHeapScanState * ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
BitmapIndexScanState * ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
BitmapOrState * ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
CteScanState * ExecInitCteScan(CteScan *node, EState *estate, int eflags)
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:369
HashJoinState * ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
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)
MaterialState * ExecInitMaterial(Material *node, EState *estate, int eflags)
MemoizeState * ExecInitMemoize(Memoize *node, EState *estate, int eflags)
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)
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)
SetOpState * ExecInitSetOp(SetOp *node, EState *estate, int eflags)
Definition nodeSetOp.c:572
SortState * ExecInitSort(Sort *node, EState *estate, int eflags)
Definition nodeSort.c:221
SubPlanState * ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
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)
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)
Instrumentation * instrument
Definition execnodes.h:1177
List * initPlan
Definition execnodes.h:1192
bool async_capable
Definition execnodes.h:1209
ExecProcNodeMtd ExecProcNode
Definition execnodes.h:1173
List * initPlan
Definition plannodes.h:236
List * args
Definition primnodes.h:1124

References SubPlan::args, 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(), fb(), 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 
)
extern

Definition at line 2036 of file execTuples.c.

2038{
2039 TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_ops);
2040
2041 return ExecStoreAllNullTuple(slot);
2042}

References ExecInitExtraTupleSlot(), ExecStoreAllNullTuple(), and fb().

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

◆ ExecInitQual()

ExprState * ExecInitQual ( List qual,
PlanState parent 
)
extern

Definition at line 229 of file execExpr.c.

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

References Assert, EEO_FLAG_IS_QUAL, EEOP_DONE_RETURN, EEOP_QUAL, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), fb(), foreach_int, foreach_ptr, IsA, lappend_int(), makeNode, and NIL.

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,
Bitmapset unpruned_relids 
)
extern

Definition at line 773 of file execUtils.c.

775{
776 /* Remember the range table List as-is */
777 estate->es_range_table = rangeTable;
778
779 /* ... and the RTEPermissionInfo List too */
780 estate->es_rteperminfos = permInfos;
781
782 /* Set size of associated arrays */
784
785 /*
786 * Initialize the bitmapset of RT indexes (es_unpruned_relids)
787 * representing relations that will be scanned during execution. This set
788 * is initially populated by the caller and may be extended later by
789 * ExecDoInitialPruning() to include RT indexes of unpruned leaf
790 * partitions.
791 */
793
794 /*
795 * Allocate an array to store an open Relation corresponding to each
796 * rangetable entry, and initialize entries to NULL. Relations are opened
797 * and stored here as needed.
798 */
799 estate->es_relations = (Relation *)
800 palloc0(estate->es_range_table_size * sizeof(Relation));
801
802 /*
803 * es_result_relations and es_rowmarks are also parallel to
804 * es_range_table, but are allocated only if needed.
805 */
806 estate->es_result_relations = NULL;
807 estate->es_rowmarks = NULL;
808}

References EState::es_range_table, EState::es_range_table_size, EState::es_relations, EState::es_result_relations, EState::es_rowmarks, EState::es_rteperminfos, EState::es_unpruned_relids, fb(), 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 
)
extern

Definition at line 880 of file execUtils.c.

882{
884
886 InitResultRelInfo(resultRelInfo,
888 rti,
889 NULL,
890 estate->es_instrument);
891
892 if (estate->es_result_relations == NULL)
894 palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
895 estate->es_result_relations[rti - 1] = resultRelInfo;
896
897 /*
898 * Saving in the list allows to avoid needlessly traversing the whole
899 * array when only a few of its entries are possibly non-NULL.
900 */
902 lappend(estate->es_opened_result_relations, resultRelInfo);
903}
Relation ExecGetRangeTableRelation(EState *estate, Index rti, bool isResultRel)
Definition execUtils.c:825

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

Referenced by CopyFrom(), and ExecInitModifyTable().

◆ ExecInitResultSlot()

void ExecInitResultSlot ( PlanState planstate,
const TupleTableSlotOps tts_ops 
)
extern

Definition at line 1968 of file execTuples.c.

1969{
1970 TupleTableSlot *slot;
1971
1972 slot = ExecAllocTableSlot(&planstate->state->es_tupleTable,
1973 planstate->ps_ResultTupleDesc, tts_ops);
1974 planstate->ps_ResultTupleSlot = slot;
1975
1976 planstate->resultopsfixed = planstate->ps_ResultTupleDesc != NULL;
1977 planstate->resultops = tts_ops;
1978 planstate->resultopsset = true;
1979}
EState * state
Definition execnodes.h:1169

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

Referenced by ExecConditionalAssignProjectionInfo(), and ExecInitResultTupleSlotTL().

◆ ExecInitResultTupleSlotTL()

◆ ExecInitResultTypeTL()

◆ ExecInitScanTupleSlot()

void ExecInitScanTupleSlot ( EState estate,
ScanState scanstate,
TupleDesc  tupledesc,
const TupleTableSlotOps tts_ops 
)
extern

◆ ExecInitTableFunctionResult()

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

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 
)
extern

Definition at line 310 of file execIndexing.c.

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

References Assert, CEOUC_LIVELOCK_PREVENTING_WAIT, CEOUC_NOWAIT, CEOUC_WAIT, check_exclusion_or_unique_constraint(), ExprContext::ecxt_scantuple, ExecPrepareQual(), ExecQual(), fb(), 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 
)
extern

Definition at line 4583 of file nodeModifyTable.c.

4585{
4586 if (node->mt_resultOidHash)
4587 {
4588 /* Use the pre-built hash table to locate the rel */
4590
4593 if (mtlookup)
4594 {
4595 if (update_cache)
4596 {
4598 node->mt_lastResultIndex = mtlookup->relationIndex;
4599 }
4600 return node->resultRelInfo + mtlookup->relationIndex;
4601 }
4602 }
4603 else
4604 {
4605 /* With few target rels, just search the ResultRelInfo array */
4606 for (int ndx = 0; ndx < node->mt_nrels; ndx++)
4607 {
4609
4610 if (RelationGetRelid(rInfo->ri_RelationDesc) == resultoid)
4611 {
4612 if (update_cache)
4613 {
4615 node->mt_lastResultIndex = ndx;
4616 }
4617 return rInfo;
4618 }
4619 }
4620 }
4621
4622 if (!missing_ok)
4623 elog(ERROR, "incorrect result relation OID %u", resultoid);
4624 return NULL;
4625}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
@ HASH_FIND
Definition hsearch.h:113
ResultRelInfo * resultRelInfo
Definition execnodes.h:1410
HTAB * mt_resultOidHash
Definition execnodes.h:1432

References elog, ERROR, fb(), HASH_FIND, hash_search(), ModifyTableState::mt_lastResultIndex, ModifyTableState::mt_lastResultOid, ModifyTableState::mt_nrels, ModifyTableState::mt_resultOidHash, RelationGetRelid, and ModifyTableState::resultRelInfo.

Referenced by ExecFindPartition(), and ExecModifyTable().

◆ ExecMakeFunctionResultSet()

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

Definition at line 497 of file execSRF.c.

502{
504 Datum result;
505 FunctionCallInfo fcinfo;
508 bool callit;
509 int i;
510
511restart:
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;
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 */
533 foundTup = tuplestore_gettupleslot(fcache->funcResultStore, true, false,
534 fcache->funcResultSlot);
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;
544 return ExecFetchSlotHeapTupleDatum(fcache->funcResultSlot);
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 */
553 tuplestore_end(fcache->funcResultStore);
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 {
575
576 ExecEvalFuncArgs(fcinfo, arguments, econtext);
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;
592 rsinfo.econtext = econtext;
593 rsinfo.expectedDesc = fcache->funcResultDesc;
594 rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
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 {
621
622 fcinfo->isnull = false;
623 rsinfo.isDone = ExprSingleResult;
624 result = FunctionCallInvoke(fcinfo);
625 *isNull = fcinfo->isnull;
626 *isDone = rsinfo.isDone;
627
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 {
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)
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 */
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
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)
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
Definition execUtils.c:963
@ ExprSingleResult
Definition execnodes.h:329
@ ExprMultipleResult
Definition execnodes.h:330
@ ExprEndResult
Definition execnodes.h:331
@ SFRM_ValuePerCall
Definition execnodes.h:342
@ SFRM_Materialize
Definition execnodes.h:343
#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)
NodeTag type
Definition nodes.h:136
MemoryContext tts_mcxt
Definition tuptable.h:127
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
void tuplestore_end(Tuplestorestate *state)
Definition tuplestore.c:492

References FunctionCallInfoBaseData::args, check_stack_depth(), ereport, errcode(), errmsg(), ERROR, ExecEvalFuncArgs(), ExecFetchSlotHeapTupleDatum(), ExecPrepareTuplestoreResult(), ExprEndResult, ExprMultipleResult, ExprSingleResult, fb(), FunctionCallInvoke, i, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, MemoryContextSwitchTo(), FunctionCallInfoBaseData::nargs, pgstat_end_function_usage(), pgstat_init_function_usage(), PointerGetDatum(), RegisterExprContextCallback(), FunctionCallInfoBaseData::resultinfo, SFRM_Materialize, SFRM_ValuePerCall, ShutdownSetExpr(), slot_getattr(), TupleTableSlot::tts_mcxt, tuplestore_end(), tuplestore_gettupleslot(), and Node::type.

Referenced by ExecProjectSRF().

◆ ExecMakeTableFunctionResult()

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

Definition at line 101 of file execSRF.c.

106{
107 Tuplestorestate *tupstore = NULL;
108 TupleDesc tupdesc = NULL;
110 bool returnsTuple;
111 bool returnsSet = false;
112 FunctionCallInfo fcinfo;
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 */
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 */
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)
196 }
197 }
198 }
199 else
200 {
201 /* Treat setexpr as a generic expression */
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 {
231
232 fcinfo->isnull = false;
233 rsinfo.isDone = ExprSingleResult;
234 result = FunctionCallInvoke(fcinfo);
235
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",
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)
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)
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)
373 errmsg("table-function protocol for materialize mode was not followed")));
374 /* Done evaluating the set result */
375 break;
376 }
377 else
380 errmsg("unrecognized table-function returnMode: %d",
381 (int) rsinfo.returnMode)));
382
383 first_time = false;
384 }
385
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
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:345
@ SFRM_Materialize_Random
Definition execnodes.h:344
#define ResetExprContext(econtext)
Definition executor.h:650
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:393
#define DatumGetHeapTupleHeader(X)
Definition fmgr.h:296
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
bool type_is_rowtype(Oid typid)
Definition lsyscache.c:2805
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
bool fn_strict
Definition fmgr.h:61
Expr * expr
Definition execnodes.h:944
FunctionCallInfo fcinfo
Definition execnodes.h:1004
bool funcReturnsSet
Definition execnodes.h:980
ExprState * elidedFuncState
Definition execnodes.h:952
FmgrInfo func
Definition execnodes.h:959
List * args
Definition execnodes.h:945
int32 tdtypmod
Definition tupdesc.h:139
void FreeTupleDesc(TupleDesc tupdesc)
Definition tupdesc.c:502
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:182
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:842
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition tuplestore.c:330
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:784
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition tuplestore.c:764
TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
Definition typcache.c:1955

References FunctionCallInfoBaseData::args, SetExprState::args, Assert, CHECK_FOR_INTERRUPTS, CreateTemplateTupleDesc(), CurrentMemoryContext, DatumGetHeapTupleHeader, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, SetExprState::elidedFuncState, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr(), ExecEvalFuncArgs(), SetExprState::expr, ExprEndResult, ExprMultipleResult, ExprSingleResult, exprType(), fb(), SetExprState::fcinfo, FmgrInfo::fn_strict, FunctionCallInfoBaseData::fncollation, FreeTupleDesc(), SetExprState::func, SetExprState::funcReturnsSet, FunctionCallInvoke, HeapTupleHeaderGetDatumLength(), HeapTupleHeaderGetTypeId(), HeapTupleHeaderGetTypMod(), i, InitFunctionCallInfoData, InvalidOid, 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, SFRM_Materialize, SFRM_Materialize_Preferred, SFRM_Materialize_Random, SFRM_ValuePerCall, SizeForFunctionCallInfo, TupleDescData::tdtypeid, TupleDescData::tdtypmod, tupledesc_match(), TupleDescInitEntry(), tuplestore_begin_heap(), tuplestore_puttuple(), tuplestore_putvalues(), type_is_rowtype(), and work_mem.

Referenced by FunctionNext().

◆ ExecMarkPos()

void ExecMarkPos ( PlanState node)
extern

Definition at line 327 of file execAmi.c.

328{
329 switch (nodeTag(node))
330 {
331 case T_IndexScanState:
333 break;
334
337 break;
338
341 break;
342
343 case T_MaterialState:
345 break;
346
347 case T_SortState:
348 ExecSortMarkPos((SortState *) node);
349 break;
350
351 case T_ResultState:
353 break;
354
355 default:
356 /* don't make hard error unless caller asks to restore... */
357 elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
358 break;
359 }
360}
#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)
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(), fb(), and nodeTag.

Referenced by ExecMergeJoin(), and ExecResultMarkPos().

◆ ExecMaterializesOutput()

bool ExecMaterializesOutput ( NodeTag  plantype)
extern

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:
644 case T_WorkTableScan:
645 case T_Sort:
646 return true;
647
648 default:
649 break;
650 }
651
652 return false;
653}

References fb().

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

◆ ExecOpenIndices()

void ExecOpenIndices ( ResultRelInfo resultRelInfo,
bool  speculative 
)
extern

Definition at line 161 of file execIndexing.c.

162{
163 Relation resultRelation = resultRelInfo->ri_RelationDesc;
165 ListCell *l;
166 int len,
167 i;
170
171 resultRelInfo->ri_NumIndices = 0;
172
173 /* fast path if no indexes */
174 if (!RelationGetForm(resultRelation)->relhasindex)
175 return;
176
177 /*
178 * Get cached list of index OIDs
179 */
180 indexoidlist = RelationGetIndexList(resultRelation);
182 if (len == 0)
183 return;
184
185 /* This Assert will fail if ExecOpenIndices is called twice */
186 Assert(resultRelInfo->ri_IndexRelationDescs == NULL);
187
188 /*
189 * allocate space for result arrays
190 */
193
194 resultRelInfo->ri_NumIndices = len;
195 resultRelInfo->ri_IndexRelationDescs = relationDescs;
196 resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
197
198 /*
199 * For each index, open the index relation and save pg_index info. We
200 * acquire RowExclusiveLock, signifying we will update the index.
201 *
202 * Note: we do this even if the index is not indisready; it's not worth
203 * the trouble to optimize for the case where it isn't.
204 */
205 i = 0;
206 foreach(l, indexoidlist)
207 {
208 Oid indexOid = lfirst_oid(l);
210 IndexInfo *ii;
211
213
214 /* extract index key information from the index's pg_index info */
216
217 /*
218 * If the indexes are to be used for speculative insertion, add extra
219 * information required by unique index entries.
220 */
221 if (speculative && ii->ii_Unique && !indexDesc->rd_index->indisexclusion)
223
225 indexInfoArray[i] = ii;
226 i++;
227 }
228
230}
#define palloc_array(type, count)
Definition fe_memutils.h:76
IndexInfo * BuildIndexInfo(Relation index)
Definition index.c:2426
void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
Definition index.c:2667
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:508
List * RelationGetIndexList(Relation relation)
Definition relcache.c:4831

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

Referenced by apply_handle_delete(), apply_handle_insert(), apply_handle_update_internal(), CatalogOpenIndexes(), CopyFrom(), ExecInitPartitionInfo(), ExecInsert(), and ExecUpdatePrologue().

◆ ExecOpenScanRelation()

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

Definition at line 742 of file execUtils.c.

743{
744 Relation rel;
745
746 /* Open the relation. */
747 rel = ExecGetRangeTableRelation(estate, scanrelid, false);
748
749 /*
750 * Complain if we're attempting a scan of an unscannable relation, except
751 * when the query won't actually be run. This is a slightly klugy place
752 * to do this, perhaps, but there is no better place.
753 */
754 if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
758 errmsg("materialized view \"%s\" has not been populated",
760 errhint("Use the REFRESH MATERIALIZED VIEW command.")));
761
762 return rel;
763}
#define EXEC_FLAG_WITH_NO_DATA
Definition executor.h:72
#define EXEC_FLAG_EXPLAIN_ONLY
Definition executor.h:66
#define RelationIsScannable(relation)
Definition rel.h:678

References ereport, errcode(), errhint(), errmsg(), ERROR, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_WITH_NO_DATA, ExecGetRangeTableRelation(), fb(), 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 
)
extern

Definition at line 1860 of file execMain.c.

1862{
1863 ExprContext *econtext;
1864 bool success;
1865
1866 /*
1867 * If first time through, build expression state tree for the partition
1868 * check expression. (In the corner case where the partition check
1869 * expression is empty, ie there's a default partition and nothing else,
1870 * we'll be fooled into executing this code each time through. But it's
1871 * pretty darn cheap in that case, so we don't worry about it.)
1872 */
1873 if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1874 {
1875 /*
1876 * Ensure that the qual tree and prepared expression are in the
1877 * query-lifespan context.
1878 */
1880 List *qual = RelationGetPartitionQual(resultRelInfo->ri_RelationDesc);
1881
1882 resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1884 }
1885
1886 /*
1887 * We will use the EState's per-tuple context for evaluating constraint
1888 * expressions (creating it if it's not already there).
1889 */
1890 econtext = GetPerTupleExprContext(estate);
1891
1892 /* Arrange for econtext's scan tuple to be the tuple under test */
1893 econtext->ecxt_scantuple = slot;
1894
1895 /*
1896 * As in case of the cataloged constraints, we treat a NULL result as
1897 * success here, not a failure.
1898 */
1899 success = ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
1900
1901 /* if asked to emit error, don't actually return on failure */
1902 if (!success && emitError)
1903 ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
1904
1905 return success;
1906}
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition execExpr.c:872
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition execExpr.c:816
void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition execMain.c:1913
static bool success
Definition initdb.c:187
List * RelationGetPartitionQual(Relation rel)
Definition partcache.c:277
ExprState * ri_PartitionCheckExpr
Definition execnodes.h:594

References ExprContext::ecxt_scantuple, EState::es_query_cxt, ExecCheck(), ExecPartitionCheckEmitError(), ExecPrepareCheck(), fb(), 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 
)
extern

Definition at line 1913 of file execMain.c.

1916{
1918 TupleDesc tupdesc;
1919 char *val_desc;
1921
1922 /*
1923 * If the tuple has been routed, it's been converted to the partition's
1924 * rowtype, which might differ from the root table's. We must convert it
1925 * back to the root table's rowtype so that val_desc in the error message
1926 * matches the input tuple.
1927 */
1928 if (resultRelInfo->ri_RootResultRelInfo)
1929 {
1930 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1932 AttrMap *map;
1933
1934 root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
1935 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1936
1938 /* a reverse map */
1939 map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc, false);
1940
1941 /*
1942 * Partition-specific slot's tupdesc can't be changed, so allocate a
1943 * new one.
1944 */
1945 if (map != NULL)
1946 slot = execute_attr_map_slot(map, slot,
1949 ExecGetUpdatedCols(rootrel, estate));
1950 }
1951 else
1952 {
1954 tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1955 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1956 ExecGetUpdatedCols(resultRelInfo, estate));
1957 }
1958
1960 slot,
1961 tupdesc,
1963 64);
1964 ereport(ERROR,
1966 errmsg("new row for relation \"%s\" violates partition constraint",
1968 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1969 errtable(resultRelInfo->ri_RelationDesc)));
1970}
int errtable(Relation rel)
Definition relcache.c:6044

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

Referenced by ExecCrossPartitionUpdate(), and ExecPartitionCheck().

◆ ExecPrepareCheck()

ExprState * ExecPrepareCheck ( List qual,
EState estate 
)
extern

Definition at line 816 of file execExpr.c.

817{
818 ExprState *result;
819 MemoryContext oldcontext;
820
821 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
822
823 qual = (List *) expression_planner((Expr *) qual);
824
825 result = ExecInitCheck(qual, NULL);
826
827 MemoryContextSwitchTo(oldcontext);
828
829 return result;
830}
ExprState * ExecInitCheck(List *qual, PlanState *parent)
Definition execExpr.c:315
Expr * expression_planner(Expr *expr)
Definition planner.c:6817

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

Referenced by ExecPartitionCheck().

◆ ExecPrepareExpr()

◆ ExecPrepareExprList()

List * ExecPrepareExprList ( List nodes,
EState estate 
)
extern

Definition at line 839 of file execExpr.c.

840{
841 List *result = NIL;
842 MemoryContext oldcontext;
843 ListCell *lc;
844
845 /* Ensure that the list cell nodes are in the right context too */
846 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
847
848 foreach(lc, nodes)
849 {
850 Expr *e = (Expr *) lfirst(lc);
851
852 result = lappend(result, ExecPrepareExpr(e, estate));
853 }
854
855 MemoryContextSwitchTo(oldcontext);
856
857 return result;
858}
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition execExpr.c:765

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

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

◆ ExecPrepareQual()

ExprState * ExecPrepareQual ( List qual,
EState estate 
)
extern

Definition at line 793 of file execExpr.c.

794{
795 ExprState *result;
796 MemoryContext oldcontext;
797
798 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
799
800 qual = (List *) expression_planner((Expr *) qual);
801
802 result = ExecInitQual(qual, NULL);
803
804 MemoryContextSwitchTo(oldcontext);
805
806 return result;
807}
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:229

References EState::es_query_cxt, ExecInitQual(), expression_planner(), fb(), 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 483 of file executor.h.

484{
485 ExprContext *econtext = projInfo->pi_exprContext;
486 ExprState *state = &projInfo->pi_state;
487 TupleTableSlot *slot = state->resultslot;
488
489 /*
490 * Clear any former contents of the result slot. This makes it safe for
491 * us to use the slot's Datum/isnull arrays as workspace.
492 */
493 ExecClearTuple(slot);
494
495 /* Run the expression */
497
498 /*
499 * Successfully formed a result row. Mark the result slot as containing a
500 * valid virtual tuple (inlined version of ExecStoreVirtualTuple()).
501 */
502 slot->tts_flags &= ~TTS_FLAG_EMPTY;
503 slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
504
505 return slot;
506}
static void ExecEvalExprNoReturnSwitchContext(ExprState *state, ExprContext *econtext)
Definition executor.h:458
AttrNumber tts_nvalid
Definition tuptable.h:119
uint16 tts_flags
Definition tuptable.h:117

References ExecClearTuple(), ExecEvalExprNoReturnSwitchContext(), fb(), TupleDescData::natts, 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(), ExecScanExtended(), ExecWindowAgg(), MJFillInner(), MJFillOuter(), and project_aggregates().

◆ ExecQual()

static bool ExecQual ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 519 of file executor.h.

520{
521 Datum ret;
522 bool isnull;
523
524 /* short-circuit (here and in ExecInitQual) for empty restriction list */
525 if (state == NULL)
526 return true;
527
528 /* verify that expression was compiled using ExecInitQual */
529 Assert(state->flags & EEO_FLAG_IS_QUAL);
530
531 ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
532
533 /* EEOP_QUAL should never return NULL */
534 Assert(!isnull);
535
536 return DatumGetBool(ret);
537}

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

Referenced by agg_retrieve_direct(), compute_index_stats(), CopyFrom(), ExecCheckIndexConstraints(), ExecEvalPreOrderedDistinctMulti(), ExecGroup(), ExecHashJoinImpl(), ExecInsertIndexTuples(), ExecMergeJoin(), ExecMergeMatched(), ExecMergeNotMatched(), ExecNestLoop(), ExecOnConflictUpdate(), ExecQualAndReset(), ExecResult(), ExecScanExtended(), 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 
)
extern

Definition at line 729 of file execUtils.c.

730{
731 return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
732}
bool list_member_int(const List *list, int datum)
Definition list.c:702
List * resultRelations
Definition plannodes.h:124

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

◆ ExecRelGenVirtualNotNull()

AttrNumber ExecRelGenVirtualNotNull ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate,
List notnull_virtual_attrs 
)
extern

Definition at line 2098 of file execMain.c.

2100{
2101 Relation rel = resultRelInfo->ri_RelationDesc;
2102 ExprContext *econtext;
2104
2105 /*
2106 * We implement this by building a NullTest node for each virtual
2107 * generated column, which we cache in resultRelInfo, and running those
2108 * through ExecCheck().
2109 */
2110 if (resultRelInfo->ri_GenVirtualNotNullConstraintExprs == NULL)
2111 {
2115
2117 {
2120
2121 /* "generated_expression IS NOT NULL" check. */
2124 nnulltest->nulltesttype = IS_NOT_NULL;
2125 nnulltest->argisrow = false;
2126 nnulltest->location = -1;
2127
2128 resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i] =
2129 ExecPrepareExpr((Expr *) nnulltest, estate);
2130 }
2132 }
2133
2134 /*
2135 * We will use the EState's per-tuple context for evaluating virtual
2136 * generated column not null constraint expressions (creating it if it's
2137 * not already there).
2138 */
2139 econtext = GetPerTupleExprContext(estate);
2140
2141 /* Arrange for econtext's scan tuple to be the tuple under test */
2142 econtext->ecxt_scantuple = slot;
2143
2144 /* And evaluate the check constraints for virtual generated column */
2146 {
2148 ExprState *exprstate = resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i];
2149
2150 Assert(exprstate != NULL);
2151 if (!ExecCheck(exprstate, econtext))
2152 return attnum;
2153 }
2154
2155 /* InvalidAttrNumber result means no error */
2156 return InvalidAttrNumber;
2157}
@ IS_NOT_NULL
Definition primnodes.h:1977
Node * build_generation_expression(Relation rel, int attrno)
ExprState ** ri_GenVirtualNotNullConstraintExprs
Definition execnodes.h:563

References Assert, attnum, build_generation_expression(), ExprContext::ecxt_scantuple, EState::es_query_cxt, ExecCheck(), ExecPrepareExpr(), fb(), foreach_current_index, foreach_int, GetPerTupleExprContext, i, InvalidAttrNumber, IS_NOT_NULL, list_length(), makeNode, MemoryContextSwitchTo(), palloc0_array, ResultRelInfo::ri_GenVirtualNotNullConstraintExprs, and ResultRelInfo::ri_RelationDesc.

Referenced by ATRewriteTable(), and ExecConstraints().

◆ ExecReScan()

void ExecReScan ( PlanState node)
extern

Definition at line 77 of file execAmi.c.

78{
79 /* If collecting timing stats, update them */
80 if (node->instrument)
82
83 /*
84 * If we have changed parameters, propagate that info.
85 *
86 * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
87 * corresponding to the output param(s) that the InitPlan will update.
88 * Since we make only one pass over the list, that means that an InitPlan
89 * can depend on the output param(s) of a sibling InitPlan only if that
90 * sibling appears earlier in the list. This is workable for now given
91 * the limited ways in which one InitPlan could depend on another, but
92 * eventually we might need to work harder (or else make the planner
93 * enlarge the extParam/allParam sets to include the params of depended-on
94 * InitPlans).
95 */
96 if (node->chgParam != NULL)
97 {
98 ListCell *l;
99
100 foreach(l, node->initPlan)
101 {
102 SubPlanState *sstate = (SubPlanState *) lfirst(l);
103 PlanState *splan = sstate->planstate;
104
105 if (splan->plan->extParam != NULL) /* don't care about child
106 * local Params */
107 UpdateChangedParamSet(splan, node->chgParam);
108 if (splan->chgParam != NULL)
109 ExecReScanSetParamPlan(sstate, node);
110 }
111 foreach(l, node->subPlan)
112 {
113 SubPlanState *sstate = (SubPlanState *) lfirst(l);
114 PlanState *splan = sstate->planstate;
115
116 if (splan->plan->extParam != NULL)
117 UpdateChangedParamSet(splan, node->chgParam);
118 }
119 /* Well. Now set chgParam for child trees. */
120 if (outerPlanState(node) != NULL)
122 if (innerPlanState(node) != NULL)
124 }
125
126 /* Call expression callbacks */
127 if (node->ps_ExprContext)
129
130 /* And do node-type-specific processing */
131 switch (nodeTag(node))
132 {
133 case T_ResultState:
135 break;
136
139 break;
140
143 break;
144
145 case T_AppendState:
147 break;
148
151 break;
152
155 break;
156
157 case T_BitmapAndState:
159 break;
160
161 case T_BitmapOrState:
163 break;
164
165 case T_SeqScanState:
167 break;
168
171 break;
172
173 case T_GatherState:
175 break;
176
179 break;
180
181 case T_IndexScanState:
183 break;
184
187 break;
188
191 break;
192
195 break;
196
197 case T_TidScanState:
199 break;
200
203 break;
204
207 break;
208
211 break;
212
215 break;
216
219 break;
220
221 case T_CteScanState:
223 break;
224
227 break;
228
231 break;
232
235 break;
236
239 break;
240
241 case T_NestLoopState:
243 break;
244
245 case T_MergeJoinState:
247 break;
248
249 case T_HashJoinState:
251 break;
252
253 case T_MaterialState:
255 break;
256
257 case T_MemoizeState:
259 break;
260
261 case T_SortState:
262 ExecReScanSort((SortState *) node);
263 break;
264
267 break;
268
269 case T_GroupState:
270 ExecReScanGroup((GroupState *) node);
271 break;
272
273 case T_AggState:
274 ExecReScanAgg((AggState *) node);
275 break;
276
277 case T_WindowAggState:
279 break;
280
281 case T_UniqueState:
283 break;
284
285 case T_HashState:
286 ExecReScanHash((HashState *) node);
287 break;
288
289 case T_SetOpState:
290 ExecReScanSetOp((SetOpState *) node);
291 break;
292
293 case T_LockRowsState:
295 break;
296
297 case T_LimitState:
298 ExecReScanLimit((LimitState *) node);
299 break;
300
301 default:
302 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
303 break;
304 }
305
306 if (node->chgParam != NULL)
307 {
308 bms_free(node->chgParam);
309 node->chgParam = NULL;
310 }
311}
void ReScanExprContext(ExprContext *econtext)
Definition execUtils.c:443
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition execUtils.c:910
void InstrEndLoop(Instrumentation *instr)
Definition instrument.c:140
void ExecReScanAgg(AggState *node)
Definition nodeAgg.c:4460
void ExecReScanAppend(AppendState *node)
Definition nodeAppend.c:421
void ExecReScanBitmapAnd(BitmapAndState *node)
void ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
void ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
void ExecReScanBitmapOr(BitmapOrState *node)
void ExecReScanCteScan(CteScanState *node)
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:442
void ExecReScanGroup(GroupState *node)
Definition nodeGroup.c:235
void ExecReScanHash(HashState *node)
Definition nodeHash.c:2380
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)
void ExecReScanMaterial(MaterialState *node)
void ExecReScanMemoize(MemoizeState *node)
void ExecReScanMergeAppend(MergeAppendState *node)
void ExecReScanMergeJoin(MergeJoinState *node)
void ExecReScanModifyTable(ModifyTableState *node)
void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
void ExecReScanNestLoop(NestLoopState *node)
void ExecReScanProjectSet(ProjectSetState *node)
void ExecReScanRecursiveUnion(RecursiveUnionState *node)
void ExecReScanResult(ResultState *node)
Definition nodeResult.c:249
void ExecReScanSampleScan(SampleScanState *node)
void ExecReScanSeqScan(SeqScanState *node)
void ExecReScanSetOp(SetOpState *node)
Definition nodeSetOp.c:703
void ExecReScanSort(SortState *node)
Definition nodeSort.c:362
void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
void ExecReScanSubqueryScan(SubqueryScanState *node)
void ExecReScanTableFuncScan(TableFuncScanState *node)
void ExecReScanTidRangeScan(TidRangeScanState *node)
void ExecReScanTidScan(TidScanState *node)
void ExecReScanUnique(UniqueState *node)
Definition nodeUnique.c:175
void ExecReScanValuesScan(ValuesScanState *node)
void ExecReScanWindowAgg(WindowAggState *node)
void ExecReScanWorkTableScan(WorkTableScanState *node)
List * subPlan
Definition execnodes.h:1194
Bitmapset * extParam
Definition plannodes.h:249
PlanState * planstate
Definition execnodes.h:1015

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(), Plan::extParam, fb(), PlanState::initPlan, innerPlanState, InstrEndLoop(), PlanState::instrument, lfirst, nodeTag, outerPlanState, PlanState::plan, SubPlanState::planstate, PlanState::ps_ExprContext, ReScanExprContext(), 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)
extern

Definition at line 376 of file execAmi.c.

377{
378 switch (nodeTag(node))
379 {
380 case T_IndexScanState:
382 break;
383
386 break;
387
390 break;
391
392 case T_MaterialState:
394 break;
395
396 case T_SortState:
397 ExecSortRestrPos((SortState *) node);
398 break;
399
400 case T_ResultState:
402 break;
403
404 default:
405 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
406 break;
407 }
408}
void ExecCustomRestrPos(CustomScanState *node)
Definition nodeCustom.c:150
void ExecIndexOnlyRestrPos(IndexOnlyScanState *node)
void ExecIndexRestrPos(IndexScanState *node)
void ExecMaterialRestrPos(MaterialState *node)
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(), fb(), and nodeTag.

Referenced by ExecMergeJoin(), and ExecResultRestrPos().

◆ ExecScan()

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

Definition at line 47 of file execScan.c.

50{
51 EPQState *epqstate;
52 ExprState *qual;
54
55 epqstate = node->ps.state->es_epq_active;
56 qual = node->ps.qual;
57 projInfo = node->ps.ps_ProjInfo;
58
59 return ExecScanExtended(node,
62 epqstate,
63 qual,
64 projInfo);
65}
static pg_attribute_always_inline TupleTableSlot * ExecScanExtended(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd, EPQState *epqstate, ExprState *qual, ProjectionInfo *projInfo)
Definition execScan.h:160
struct EPQState * es_epq_active
Definition execnodes.h:744
ExprState * qual
Definition execnodes.h:1188

References EState::es_epq_active, ExecScanExtended(), fb(), ScanState::ps, PlanState::ps_ProjInfo, PlanState::qual, and PlanState::state.

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

◆ ExecScanReScan()

void ExecScanReScan ( ScanState node)
extern

Definition at line 108 of file execScan.c.

109{
110 EState *estate = node->ps.state;
111
112 /*
113 * We must clear the scan tuple so that observers (e.g., execCurrent.c)
114 * can tell that this plan node is not positioned on a tuple.
115 */
117
118 /*
119 * Rescan EvalPlanQual tuple(s) if we're inside an EvalPlanQual recheck.
120 * But don't lose the "blocked" status of blocked target relations.
121 */
122 if (estate->es_epq_active != NULL)
123 {
124 EPQState *epqstate = estate->es_epq_active;
125 Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
126
127 if (scanrelid > 0)
128 epqstate->relsubs_done[scanrelid - 1] =
129 epqstate->relsubs_blocked[scanrelid - 1];
130 else
131 {
132 Bitmapset *relids;
133 int rtindex = -1;
134
135 /*
136 * If an FDW or custom scan provider has replaced the join with a
137 * scan, there are multiple RTIs; reset the relsubs_done flag for
138 * all of them.
139 */
140 if (IsA(node->ps.plan, ForeignScan))
141 relids = ((ForeignScan *) node->ps.plan)->fs_base_relids;
142 else if (IsA(node->ps.plan, CustomScan))
143 relids = ((CustomScan *) node->ps.plan)->custom_relids;
144 else
145 elog(ERROR, "unexpected scan node: %d",
146 (int) nodeTag(node->ps.plan));
147
148 while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
149 {
150 Assert(rtindex > 0);
151 epqstate->relsubs_done[rtindex - 1] =
152 epqstate->relsubs_blocked[rtindex - 1];
153 }
154 }
155 }
156}

References Assert, bms_next_member(), elog, ERROR, EState::es_epq_active, ExecClearTuple(), fb(), 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 
)
extern

Definition at line 430 of file execProcnode.c.

431{
432 /*
433 * Add a wrapper around the ExecProcNode callback that checks stack depth
434 * during the first execution and maybe adds an instrumentation wrapper.
435 * When the callback is changed after execution has already begun that
436 * means we'll superfluously execute ExecProcNodeFirst, but that seems ok.
437 */
440}
static TupleTableSlot * ExecProcNodeFirst(PlanState *node)
on_exit_nicely_callback function
ExecProcNodeMtd ExecProcNodeReal
Definition execnodes.h:1174

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

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

◆ ExecSetTupleBound()

void ExecSetTupleBound ( int64  tuples_needed,
PlanState child_node 
)
extern

Definition at line 848 of file execProcnode.c.

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

References SortState::bounded, IncrementalSortState::bounded, ExecSetTupleBound(), fb(), i, IsA, outerPlanState, GatherState::tuples_needed, and GatherMergeState::tuples_needed.

Referenced by ExecSetTupleBound(), ParallelQueryMain(), and recompute_limits().

◆ ExecShutdownNode()

void ExecShutdownNode ( PlanState node)
extern

Definition at line 772 of file execProcnode.c.

773{
775}
static bool ExecShutdownNode_walker(PlanState *node, void *context)

References ExecShutdownNode_walker(), and fb().

Referenced by ExecutePlan().

◆ ExecSimpleRelationDelete()

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

Definition at line 978 of file execReplication.c.

981{
982 bool skip_tuple = false;
983 Relation rel = resultRelInfo->ri_RelationDesc;
984 ItemPointer tid = &searchslot->tts_tid;
985
987
988 /* BEFORE ROW DELETE Triggers */
989 if (resultRelInfo->ri_TrigDesc &&
990 resultRelInfo->ri_TrigDesc->trig_delete_before_row)
991 {
992 skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
993 tid, NULL, NULL, NULL, NULL, false);
994 }
995
996 if (!skip_tuple)
997 {
998 /* OK, delete the tuple */
999 simple_table_tuple_delete(rel, tid, estate->es_snapshot);
1000
1001 /* AFTER ROW DELETE Triggers */
1002 ExecARDeleteTriggers(estate, resultRelInfo,
1003 tid, NULL, NULL, false);
1004 }
1005}
TriggerDesc * ri_TrigDesc
Definition execnodes.h:517
bool trig_delete_before_row
Definition reltrigger.h:66
void simple_table_tuple_delete(Relation rel, ItemPointer tid, Snapshot snapshot)
Definition tableam.c:314
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition trigger.c:2801
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot **epqslot, TM_Result *tmresult, TM_FailureData *tmfd, bool is_merge_delete)
Definition trigger.c:2701

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

Referenced by apply_handle_delete_internal(), and apply_handle_tuple_routing().

◆ ExecSimpleRelationInsert()

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

Definition at line 806 of file execReplication.c.

808{
809 bool skip_tuple = false;
810 Relation rel = resultRelInfo->ri_RelationDesc;
811
812 /* For now we support only tables. */
813 Assert(rel->rd_rel->relkind == RELKIND_RELATION);
814
816
817 /* BEFORE ROW INSERT Triggers */
818 if (resultRelInfo->ri_TrigDesc &&
819 resultRelInfo->ri_TrigDesc->trig_insert_before_row)
820 {
821 if (!ExecBRInsertTriggers(estate, resultRelInfo, slot))
822 skip_tuple = true; /* "do nothing" */
823 }
824
825 if (!skip_tuple)
826 {
829 bool conflict = false;
830
831 /* Compute stored generated columns */
832 if (rel->rd_att->constr &&
834 ExecComputeStoredGenerated(resultRelInfo, estate, slot,
835 CMD_INSERT);
836
837 /* Check the constraints of the tuple */
838 if (rel->rd_att->constr)
839 ExecConstraints(resultRelInfo, slot, estate);
840 if (rel->rd_rel->relispartition)
841 ExecPartitionCheck(resultRelInfo, slot, estate, true);
842
843 /* OK, store the tuple and create index entries for it */
844 simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot);
845
847
848 if (resultRelInfo->ri_NumIndices > 0)
850 slot, estate, false,
851 conflictindexes ? true : false,
852 &conflict,
854
855 /*
856 * Checks the conflict indexes to fetch the conflicting local row and
857 * reports the conflict. We perform this check here, instead of
858 * performing an additional index scan before the actual insertion and
859 * reporting the conflict if any conflicting rows are found. This is
860 * to avoid the overhead of executing the extra scan for each INSERT
861 * operation, even when no conflict arises, which could introduce
862 * significant overhead to replication, particularly in cases where
863 * conflicts are rare.
864 *
865 * XXX OTOH, this could lead to clean-up effort for dead tuples added
866 * in heap and index in case of conflicts. But as conflicts shouldn't
867 * be a frequent thing so we preferred to save the performance
868 * overhead of extra scan before each insertion.
869 */
870 if (conflict)
871 CheckAndReportConflict(resultRelInfo, estate, CT_INSERT_EXISTS,
872 recheckIndexes, NULL, slot);
873
874 /* AFTER ROW INSERT Triggers */
875 ExecARInsertTriggers(estate, resultRelInfo, slot,
877
878 /*
879 * XXX we should in theory pass a TransitionCaptureState object to the
880 * above to capture transition tuples, but after statement triggers
881 * don't actually get fired by replication yet anyway
882 */
883
885 }
886}
@ CT_INSERT_EXISTS
Definition conflict.h:34
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition execMain.c:1860
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition execMain.c:1984
static void CheckAndReportConflict(ResultRelInfo *resultRelInfo, EState *estate, ConflictType type, List *recheckIndexes, TupleTableSlot *searchslot, TupleTableSlot *remoteslot)
#define false
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
TupleDesc rd_att
Definition rel.h:112
List * ri_onConflictArbiterIndexes
Definition execnodes.h:582
bool trig_insert_before_row
Definition reltrigger.h:56
bool has_generated_stored
Definition tupdesc.h:46
void simple_table_tuple_insert(Relation rel, TupleTableSlot *slot)
Definition tableam.c:300
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition trigger.c:2465
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition trigger.c:2543

References Assert, CheckAndReportConflict(), CheckCmdReplicaIdentity(), CMD_INSERT, TupleDescData::constr, CT_INSERT_EXISTS, ExecARInsertTriggers(), ExecBRInsertTriggers(), ExecComputeStoredGenerated(), ExecConstraints(), ExecInsertIndexTuples(), ExecPartitionCheck(), fb(), TupleConstr::has_generated_stored, list_free(), NIL, RelationData::rd_att, RelationData::rd_rel, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_onConflictArbiterIndexes, 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 
)
extern

Definition at line 895 of file execReplication.c.

898{
899 bool skip_tuple = false;
900 Relation rel = resultRelInfo->ri_RelationDesc;
901 ItemPointer tid = &(searchslot->tts_tid);
902
903 /*
904 * We support only non-system tables, with
905 * check_publication_add_relation() accountable.
906 */
907 Assert(rel->rd_rel->relkind == RELKIND_RELATION);
909
911
912 /* BEFORE ROW UPDATE Triggers */
913 if (resultRelInfo->ri_TrigDesc &&
914 resultRelInfo->ri_TrigDesc->trig_update_before_row)
915 {
916 if (!ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
917 tid, NULL, slot, NULL, NULL, false))
918 skip_tuple = true; /* "do nothing" */
919 }
920
921 if (!skip_tuple)
922 {
926 bool conflict = false;
927
928 /* Compute stored generated columns */
929 if (rel->rd_att->constr &&
931 ExecComputeStoredGenerated(resultRelInfo, estate, slot,
932 CMD_UPDATE);
933
934 /* Check the constraints of the tuple */
935 if (rel->rd_att->constr)
936 ExecConstraints(resultRelInfo, slot, estate);
937 if (rel->rd_rel->relispartition)
938 ExecPartitionCheck(resultRelInfo, slot, estate, true);
939
940 simple_table_tuple_update(rel, tid, slot, estate->es_snapshot,
942
944
945 if (resultRelInfo->ri_NumIndices > 0 && (update_indexes != TU_None))
947 slot, estate, true,
948 conflictindexes ? true : false,
951
952 /*
953 * Refer to the comments above the call to CheckAndReportConflict() in
954 * ExecSimpleRelationInsert to understand why this check is done at
955 * this point.
956 */
957 if (conflict)
958 CheckAndReportConflict(resultRelInfo, estate, CT_UPDATE_EXISTS,
960
961 /* AFTER ROW UPDATE Triggers */
962 ExecARUpdateTriggers(estate, resultRelInfo,
963 NULL, NULL,
964 tid, NULL, slot,
965 recheckIndexes, NULL, false);
966
968 }
969}
bool IsCatalogRelation(Relation relation)
Definition catalog.c:104
@ CT_UPDATE_EXISTS
Definition conflict.h:40
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:359
TU_UpdateIndexes
Definition tableam.h:111
@ TU_Summarizing
Definition tableam.h:119
@ TU_None
Definition tableam.h:113
bool ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, TM_Result *tmresult, TM_FailureData *tmfd, bool is_merge_update)
Definition trigger.c:2971
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:3144

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

Referenced by apply_handle_tuple_routing(), and apply_handle_update_internal().

◆ ExecSupportsBackwardScan()

bool ExecSupportsBackwardScan ( Plan node)
extern

Definition at line 511 of file execAmi.c.

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

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

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

◆ ExecSupportsMarkRestore()

bool ExecSupportsMarkRestore ( Path pathnode)
extern

Definition at line 418 of file execAmi.c.

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

References Assert, castNode, CUSTOMPATH_SUPPORT_MARK_RESTORE, ExecSupportsMarkRestore(), fb(), IsA, linitial, list_length(), and subpath().

Referenced by ExecSupportsMarkRestore(), and final_cost_mergejoin().

◆ ExecTargetListLength()

int ExecTargetListLength ( List targetlist)
extern

Definition at line 1175 of file execUtils.c.

1176{
1177 /* This used to be more complex, but fjoins are dead */
1178 return list_length(targetlist);
1179}

References list_length().

Referenced by ExecTypeFromTLInternal().

◆ execTuplesHashPrepare()

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

Definition at line 100 of file execGrouping.c.

104{
105 int i;
106
107 *eqFuncOids = (Oid *) palloc(numCols * sizeof(Oid));
108 *hashFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
109
110 for (i = 0; i < numCols; i++)
111 {
112 Oid eq_opr = eqOperators[i];
116
117 eq_function = get_opcode(eq_opr);
118 if (!get_op_hash_functions(eq_opr,
120 elog(ERROR, "could not find hash function for hash operator %u",
121 eq_opr);
122 /* We're not supporting cross-type cases here */
124 (*eqFuncOids)[i] = eq_function;
126 }
127}
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1435
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition lsyscache.c:575

References Assert, elog, ERROR, fb(), 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 
)
extern

Definition at line 61 of file execGrouping.c.

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

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

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

◆ ExecTypeFromExprList()

TupleDesc ExecTypeFromExprList ( List exprList)
extern

Definition at line 2186 of file execTuples.c.

2187{
2189 ListCell *lc;
2190 int cur_resno = 1;
2191
2193
2194 foreach(lc, exprList)
2195 {
2196 Node *e = lfirst(lc);
2197
2199 cur_resno,
2200 NULL,
2201 exprType(e),
2202 exprTypmod(e),
2203 0);
2205 cur_resno,
2206 exprCollation(e));
2207 cur_resno++;
2208 }
2209
2210 return typeInfo;
2211}
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:301
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:821
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition tupdesc.c:1026

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

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

◆ ExecTypeFromTL()

TupleDesc ExecTypeFromTL ( List targetList)
extern

◆ ExecTypeSetColNames()

void ExecTypeSetColNames ( TupleDesc  typeInfo,
List namesList 
)
extern

Definition at line 2219 of file execTuples.c.

2220{
2221 int colno = 0;
2222 ListCell *lc;
2223
2224 /* It's only OK to change col names in a not-yet-blessed RECORD type */
2225 Assert(typeInfo->tdtypeid == RECORDOID);
2226 Assert(typeInfo->tdtypmod < 0);
2227
2228 foreach(lc, namesList)
2229 {
2230 char *cname = strVal(lfirst(lc));
2231 Form_pg_attribute attr;
2232
2233 /* Guard against too-long names list (probably can't happen) */
2234 if (colno >= typeInfo->natts)
2235 break;
2236 attr = TupleDescAttr(typeInfo, colno);
2237 colno++;
2238
2239 /*
2240 * Do nothing for empty aliases or dropped columns (these cases
2241 * probably can't arise in RECORD types, either)
2242 */
2243 if (cname[0] == '\0' || attr->attisdropped)
2244 continue;
2245
2246 /* OK, assign the column name */
2247 namestrcpy(&(attr->attname), cname);
2248 }
2249}
void namestrcpy(Name name, const char *str)
Definition name.c:233
#define strVal(v)
Definition value.h:82

References Assert, fb(), lfirst, namestrcpy(), strVal, and TupleDescAttr().

Referenced by ExecEvalWholeRowVar(), and ExecInitExprRec().

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)
extern

Definition at line 2534 of file execMain.c.

2535{
2537 Bitmapset *updatedCols;
2538
2539 /*
2540 * Compute lock mode to use. If columns that are part of the key have not
2541 * been modified, then we can use a weaker lock, allowing for better
2542 * concurrency.
2543 */
2544 updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2545 keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2547
2548 if (bms_overlap(keyCols, updatedCols))
2549 return LockTupleExclusive;
2550
2552}
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:581
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1418
@ LockTupleExclusive
Definition lockoptions.h:58
@ LockTupleNoKeyExclusive
Definition lockoptions.h:56
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition relcache.c:5298
@ INDEX_ATTR_BITMAP_KEY
Definition relcache.h:69

References bms_overlap(), ExecGetAllUpdatedCols(), fb(), INDEX_ATTR_BITMAP_KEY, LockTupleExclusive, LockTupleNoKeyExclusive, and RelationGetIndexAttrBitmap().

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

◆ executor_errposition()

int executor_errposition ( EState estate,
int  location 
)
extern

Definition at line 936 of file execUtils.c.

937{
938 int pos;
939
940 /* No-op if location was not provided */
941 if (location < 0)
942 return 0;
943 /* Can't do anything if source text is not available */
944 if (estate == NULL || estate->es_sourceText == NULL)
945 return 0;
946 /* Convert offset to character number */
947 pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
948 /* And pass it to the ereport mechanism */
949 return errposition(pos);
950}
int errposition(int cursorpos)
Definition elog.c:1480
int pg_mbstrlen_with_len(const char *mbstr, int limit)
Definition mbutils.c:1060

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

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

◆ ExecutorEnd()

void ExecutorEnd ( QueryDesc queryDesc)
extern

Definition at line 466 of file execMain.c.

467{
469 (*ExecutorEnd_hook) (queryDesc);
470 else
471 standard_ExecutorEnd(queryDesc);
472}
ExecutorEnd_hook_type ExecutorEnd_hook
Definition execMain.c:71
void standard_ExecutorEnd(QueryDesc *queryDesc)
Definition execMain.c:475

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)
extern

Definition at line 406 of file execMain.c.

407{
409 (*ExecutorFinish_hook) (queryDesc);
410 else
411 standard_ExecutorFinish(queryDesc);
412}
ExecutorFinish_hook_type ExecutorFinish_hook
Definition execMain.c:70
void standard_ExecutorFinish(QueryDesc *queryDesc)
Definition execMain.c:415

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)
extern

Definition at line 536 of file execMain.c.

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

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

Referenced by DoPortalRewind(), and PersistHoldablePortal().

◆ ExecutorRun()

void ExecutorRun ( QueryDesc queryDesc,
ScanDirection  direction,
uint64  count 
)
extern

Definition at line 297 of file execMain.c.

299{
301 (*ExecutorRun_hook) (queryDesc, direction, count);
302 else
303 standard_ExecutorRun(queryDesc, direction, count);
304}
ExecutorRun_hook_type ExecutorRun_hook
Definition execMain.c:69
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition execMain.c:307

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 
)
extern

Definition at line 122 of file execMain.c.

123{
124 /*
125 * In some cases (e.g. an EXECUTE statement or an execute message with the
126 * extended query protocol) the query_id won't be reported, so do it now.
127 *
128 * Note that it's harmless to report the query_id multiple times, as the
129 * call will be ignored if the top level query_id has already been
130 * reported.
131 */
132 pgstat_report_query_id(queryDesc->plannedstmt->queryId, false);
133
135 (*ExecutorStart_hook) (queryDesc, eflags);
136 else
137 standard_ExecutorStart(queryDesc, eflags);
138}
void pgstat_report_query_id(int64 query_id, bool force)
ExecutorStart_hook_type ExecutorStart_hook
Definition execMain.c:68
void standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition execMain.c:141
int64 queryId
Definition plannodes.h:71
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 
)
extern

Definition at line 2232 of file execMain.c.

2234{
2235 Relation rel = resultRelInfo->ri_RelationDesc;
2236 TupleDesc tupdesc = RelationGetDescr(rel);
2237 ExprContext *econtext;
2238 ListCell *l1,
2239 *l2;
2240
2241 /*
2242 * We will use the EState's per-tuple context for evaluating constraint
2243 * expressions (creating it if it's not already there).
2244 */
2245 econtext = GetPerTupleExprContext(estate);
2246
2247 /* Arrange for econtext's scan tuple to be the tuple under test */
2248 econtext->ecxt_scantuple = slot;
2249
2250 /* Check each of the constraints */
2251 forboth(l1, resultRelInfo->ri_WithCheckOptions,
2252 l2, resultRelInfo->ri_WithCheckOptionExprs)
2253 {
2255 ExprState *wcoExpr = (ExprState *) lfirst(l2);
2256
2257 /*
2258 * Skip any WCOs which are not the kind we are looking for at this
2259 * time.
2260 */
2261 if (wco->kind != kind)
2262 continue;
2263
2264 /*
2265 * WITH CHECK OPTION checks are intended to ensure that the new tuple
2266 * is visible (in the case of a view) or that it passes the
2267 * 'with-check' policy (in the case of row security). If the qual
2268 * evaluates to NULL or FALSE, then the new tuple won't be included in
2269 * the view or doesn't pass the 'with-check' policy for the table.
2270 */
2271 if (!ExecQual(wcoExpr, econtext))
2272 {
2273 char *val_desc;
2275
2276 switch (wco->kind)
2277 {
2278 /*
2279 * For WITH CHECK OPTIONs coming from views, we might be
2280 * able to provide the details on the row, depending on
2281 * the permissions on the relation (that is, if the user
2282 * could view it directly anyway). For RLS violations, we
2283 * don't include the data since we don't know if the user
2284 * should be able to view the tuple as that depends on the
2285 * USING policy.
2286 */
2287 case WCO_VIEW_CHECK:
2288 /* See the comment in ExecConstraints(). */
2289 if (resultRelInfo->ri_RootResultRelInfo)
2290 {
2291 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2293 AttrMap *map;
2294
2295 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2296 /* a reverse map */
2298 tupdesc,
2299 false);
2300
2301 /*
2302 * Partition-specific slot's tupdesc can't be changed,
2303 * so allocate a new one.
2304 */
2305 if (map != NULL)
2306 slot = execute_attr_map_slot(map, slot,
2308
2310 ExecGetUpdatedCols(rootrel, estate));
2311 rel = rootrel->ri_RelationDesc;
2312 }
2313 else
2314 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2315 ExecGetUpdatedCols(resultRelInfo, estate));
2317 slot,
2318 tupdesc,
2320 64);
2321
2322 ereport(ERROR,
2324 errmsg("new row violates check option for view \"%s\"",
2325 wco->relname),
2326 val_desc ? errdetail("Failing row contains %s.",
2327 val_desc) : 0));
2328 break;
2331 if (wco->polname != NULL)
2332 ereport(ERROR,
2334 errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
2335 wco->polname, wco->relname)));
2336 else
2337 ereport(ERROR,
2339 errmsg("new row violates row-level security policy for table \"%s\"",
2340 wco->relname)));
2341 break;
2344 if (wco->polname != NULL)
2345 ereport(ERROR,
2347 errmsg("target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2348 wco->polname, wco->relname)));
2349 else
2350 ereport(ERROR,
2352 errmsg("target row violates row-level security policy (USING expression) for table \"%s\"",
2353 wco->relname)));
2354 break;
2356 if (wco->polname != NULL)
2357 ereport(ERROR,
2359 errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2360 wco->polname, wco->relname)));
2361 else
2362 ereport(ERROR,
2364 errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
2365 wco->relname)));
2366 break;
2367 default:
2368 elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
2369 break;
2370 }
2371 }
2372 }
2373}
@ WCO_RLS_MERGE_UPDATE_CHECK
@ WCO_RLS_CONFLICT_CHECK
@ WCO_RLS_INSERT_CHECK
@ WCO_VIEW_CHECK
@ WCO_RLS_UPDATE_CHECK
@ WCO_RLS_MERGE_DELETE_CHECK
List * ri_WithCheckOptions
Definition execnodes.h:551
List * ri_WithCheckOptionExprs
Definition execnodes.h:554

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(), fb(), forboth, GetPerTupleExprContext, lfirst, MakeTupleTableSlot(), RelationGetDescr, RelationGetRelid, 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,
ExprState hashexpr 
)
extern

Definition at line 469 of file execGrouping.c.

472{
473 TupleHashEntry entry;
476
477 /* Need to run the hash functions in short-lived context */
479
480 /* Set up data needed by hash and match functions */
481 hashtable->inputslot = slot;
482 hashtable->in_hash_expr = hashexpr;
483 hashtable->cur_eq_func = eqcomp;
484
485 /* Search the hash table */
486 key = NULL; /* flag to reference inputslot */
487 entry = tuplehash_lookup(hashtable->hashtab, key);
489
490 return entry;
491}

References TupleHashTableData::cur_eq_func, fb(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_expr, TupleHashTableData::inputslot, MemoryContextSwitchTo(), and TupleHashTableData::tempcxt.

Referenced by ExecHashSubPlan().

◆ FreeExecutorState()

void FreeExecutorState ( EState estate)
extern

Definition at line 192 of file execUtils.c.

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

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

Referenced by afterTriggerInvokeEvents(), ATExecAddColumn(), 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(), MergePartitionsMoveRows(), operator_predicate_proof(), plpgsql_inline_handler(), plpgsql_xact_cb(), SplitPartitionMoveRows(), standard_ExecutorEnd(), unique_key_recheck(), and validateDomainCheckConstraint().

◆ FreeExprContext()

void FreeExprContext ( ExprContext econtext,
bool  isCommit 
)
extern

Definition at line 416 of file execUtils.c.

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

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

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

◆ GetAttributeByName()

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

Definition at line 1061 of file execUtils.c.

1062{
1064 Datum result;
1065 Oid tupType;
1067 TupleDesc tupDesc;
1069 int i;
1070
1071 if (attname == NULL)
1072 elog(ERROR, "invalid attribute name");
1073
1074 if (isNull == NULL)
1075 elog(ERROR, "a NULL isNull pointer was passed");
1076
1077 if (tuple == NULL)
1078 {
1079 /* Kinda bogus but compatible with old behavior... */
1080 *isNull = true;
1081 return (Datum) 0;
1082 }
1083
1087
1089 for (i = 0; i < tupDesc->natts; i++)
1090 {
1092
1093 if (namestrcmp(&(att->attname), attname) == 0)
1094 {
1095 attrno = att->attnum;
1096 break;
1097 }
1098 }
1099
1101 elog(ERROR, "attribute \"%s\" does not exist", attname);
1102
1103 /*
1104 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1105 * the fields in the struct just in case user tries to inspect system
1106 * columns.
1107 */
1109 ItemPointerSetInvalid(&(tmptup.t_self));
1110 tmptup.t_tableOid = InvalidOid;
1111 tmptup.t_data = tuple;
1112
1113 result = heap_getattr(&tmptup,
1114 attrno,
1115 tupDesc,
1116 isNull);
1117
1118 ReleaseTupleDesc(tupDesc);
1119
1120 return result;
1121}
int32_t int32
Definition c.h:542
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
int namestrcmp(Name name, const char *str)
Definition name.c:247
NameData attname
#define ReleaseTupleDesc(tupdesc)
Definition tupdesc.h:219
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition typcache.c:1921

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

Referenced by c_overpaid(), and overpaid().

◆ GetAttributeByNum()

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

Definition at line 1124 of file execUtils.c.

1127{
1128 Datum result;
1129 Oid tupType;
1131 TupleDesc tupDesc;
1133
1135 elog(ERROR, "invalid attribute number %d", attrno);
1136
1137 if (isNull == NULL)
1138 elog(ERROR, "a NULL isNull pointer was passed");
1139
1140 if (tuple == NULL)
1141 {
1142 /* Kinda bogus but compatible with old behavior... */
1143 *isNull = true;
1144 return (Datum) 0;
1145 }
1146
1150
1151 /*
1152 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1153 * the fields in the struct just in case user tries to inspect system
1154 * columns.
1155 */
1157 ItemPointerSetInvalid(&(tmptup.t_self));
1158 tmptup.t_tableOid = InvalidOid;
1159 tmptup.t_data = tuple;
1160
1161 result = heap_getattr(&tmptup,
1162 attrno,
1163 tupDesc,
1164 isNull);
1165
1166 ReleaseTupleDesc(tupDesc);
1167
1168 return result;
1169}

References AttributeNumberIsValid, elog, ERROR, fb(), heap_getattr(), HeapTupleHeaderGetDatumLength(), HeapTupleHeaderGetTypeId(), HeapTupleHeaderGetTypMod(), InvalidOid, ItemPointerSetInvalid(), lookup_rowtype_tupdesc(), and ReleaseTupleDesc.

◆ InitResultRelInfo()

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

Definition at line 1247 of file execMain.c.

1252{
1253 MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1254 resultRelInfo->type = T_ResultRelInfo;
1255 resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1256 resultRelInfo->ri_RelationDesc = resultRelationDesc;
1257 resultRelInfo->ri_NumIndices = 0;
1258 resultRelInfo->ri_IndexRelationDescs = NULL;
1259 resultRelInfo->ri_IndexRelationInfo = NULL;
1260 resultRelInfo->ri_needLockTagTuple =
1262 /* make a copy so as not to depend on relcache info not changing... */
1263 resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1264 if (resultRelInfo->ri_TrigDesc)
1265 {
1266 int n = resultRelInfo->ri_TrigDesc->numtriggers;
1267
1268 resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1270 resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1272 if (instrument_options)
1273 resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options, false);
1274 }
1275 else
1276 {
1277 resultRelInfo->ri_TrigFunctions = NULL;
1278 resultRelInfo->ri_TrigWhenExprs = NULL;
1279 resultRelInfo->ri_TrigInstrument = NULL;
1280 }
1281 if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1283 else
1284 resultRelInfo->ri_FdwRoutine = NULL;
1285
1286 /* The following fields are set later if needed */
1287 resultRelInfo->ri_RowIdAttNo = 0;
1288 resultRelInfo->ri_extraUpdatedCols = NULL;
1289 resultRelInfo->ri_projectNew = NULL;
1290 resultRelInfo->ri_newTupleSlot = NULL;
1291 resultRelInfo->ri_oldTupleSlot = NULL;
1292 resultRelInfo->ri_projectNewInfoValid = false;
1293 resultRelInfo->ri_FdwState = NULL;
1294 resultRelInfo->ri_usesFdwDirectModify = false;
1295 resultRelInfo->ri_CheckConstraintExprs = NULL;
1297 resultRelInfo->ri_GeneratedExprsI = NULL;
1298 resultRelInfo->ri_GeneratedExprsU = NULL;
1299 resultRelInfo->ri_projectReturning = NULL;
1300 resultRelInfo->ri_onConflictArbiterIndexes = NIL;
1301 resultRelInfo->ri_onConflict = NULL;
1302 resultRelInfo->ri_ReturningSlot = NULL;
1303 resultRelInfo->ri_TrigOldSlot = NULL;
1304 resultRelInfo->ri_TrigNewSlot = NULL;
1305 resultRelInfo->ri_AllNullSlot = NULL;
1306 resultRelInfo->ri_MergeActions[MERGE_WHEN_MATCHED] = NIL;
1309 resultRelInfo->ri_MergeJoinCondition = NULL;
1310
1311 /*
1312 * Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
1313 * non-NULL partition_root_rri. For child relations that are part of the
1314 * initial query rather than being dynamically added by tuple routing,
1315 * this field is filled in ExecInitModifyTable().
1316 */
1318 /* Set by ExecGetRootToChildMap */
1319 resultRelInfo->ri_RootToChildMap = NULL;
1320 resultRelInfo->ri_RootToChildMapValid = false;
1321 /* Set by ExecInitRoutingInfo */
1322 resultRelInfo->ri_PartitionTupleSlot = NULL;
1323 resultRelInfo->ri_ChildToRootMap = NULL;
1324 resultRelInfo->ri_ChildToRootMapValid = false;
1325 resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
1326}
#define MemSet(start, val, len)
Definition c.h:1013
@ MERGE_WHEN_NOT_MATCHED_BY_TARGET
Definition primnodes.h:2023
@ MERGE_WHEN_NOT_MATCHED_BY_SOURCE
Definition primnodes.h:2022
@ MERGE_WHEN_MATCHED
Definition primnodes.h:2021
ExprState ** ri_CheckConstraintExprs
Definition execnodes.h:557
TupleTableSlot * ri_PartitionTupleSlot
Definition execnodes.h:621
bool ri_projectNewInfoValid
Definition execnodes.h:511
OnConflictSetState * ri_onConflict
Definition execnodes.h:585
Instrumentation * ri_TrigInstrument
Definition execnodes.h:526
ExprState * ri_MergeJoinCondition
Definition execnodes.h:591
TupleTableSlot * ri_ReturningSlot
Definition execnodes.h:529
TupleTableSlot * ri_oldTupleSlot
Definition execnodes.h:509
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition execnodes.h:624
TupleTableSlot * ri_AllNullSlot
Definition execnodes.h:532
Bitmapset * ri_extraUpdatedCols
Definition execnodes.h:500
ExprState ** ri_GeneratedExprsI
Definition execnodes.h:568
void * ri_FdwState
Definition execnodes.h:538
List * ri_MergeActions[NUM_MERGE_MATCH_KINDS]
Definition execnodes.h:588
TupleTableSlot * ri_newTupleSlot
Definition execnodes.h:507
ProjectionInfo * ri_projectNew
Definition execnodes.h:505
NodeTag type
Definition execnodes.h:476
ProjectionInfo * ri_projectReturning
Definition execnodes.h:579
ExprState ** ri_GeneratedExprsU
Definition execnodes.h:569
ExprState ** ri_TrigWhenExprs
Definition execnodes.h:523
FmgrInfo * ri_TrigFunctions
Definition execnodes.h:520
bool ri_usesFdwDirectModify
Definition execnodes.h:541
AttrNumber ri_RowIdAttNo
Definition execnodes.h:497
TupleTableSlot * ri_TrigNewSlot
Definition execnodes.h:531
TupleTableSlot * ri_TrigOldSlot
Definition execnodes.h:530
int numtriggers
Definition reltrigger.h:50
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition trigger.c:2090

References CopyTriggerDesc(), fb(), GetFdwRoutineForRelation(), InstrAlloc(), IsInplaceUpdateRelation(), MemSet, MERGE_WHEN_MATCHED, MERGE_WHEN_NOT_MATCHED_BY_SOURCE, MERGE_WHEN_NOT_MATCHED_BY_TARGET, NIL, TriggerDesc::numtriggers, palloc0_array, ResultRelInfo::ri_AllNullSlot, ResultRelInfo::ri_CheckConstraintExprs, ResultRelInfo::ri_ChildToRootMap, ResultRelInfo::ri_ChildToRootMapValid, ResultRelInfo::ri_CopyMultiInsertBuffer, ResultRelInfo::ri_extraUpdatedCols, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_GeneratedExprsI, ResultRelInfo::ri_GeneratedExprsU, ResultRelInfo::ri_GenVirtualNotNullConstraintExprs, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_MergeActions, ResultRelInfo::ri_MergeJoinCondition, ResultRelInfo::ri_needLockTagTuple, ResultRelInfo::ri_newTupleSlot, 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, and ResultRelInfo::type.

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

◆ LookupTupleHashEntry()

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

Definition at line 382 of file execGrouping.c.

384{
385 TupleHashEntry entry;
388
389 /* Need to run the hash functions in short-lived context */
391
392 /* set up data needed by hash and match functions */
393 hashtable->inputslot = slot;
394 hashtable->in_hash_expr = hashtable->tab_hash_expr;
395 hashtable->cur_eq_func = hashtable->tab_eq_func;
396
398 entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, local_hash);
399
400 if (hash != NULL)
401 *hash = local_hash;
402
403 Assert(entry == NULL || entry->hash == local_hash);
404
406
407 return entry;
408}
static uint32 TupleHashTableHash_internal(struct tuplehash_hash *tb, MinimalTuple tuple)
static TupleHashEntry LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 hash)
static unsigned hash(unsigned *uv, int n)
Definition rege_dfa.c:715

References Assert, TupleHashTableData::cur_eq_func, fb(), hash(), TupleHashEntryData::hash, TupleHashTableData::hashtab, TupleHashTableData::in_hash_expr, TupleHashTableData::inputslot, LookupTupleHashEntry_internal(), MemoryContextSwitchTo(), TupleHashTableData::tab_eq_func, TupleHashTableData::tab_hash_expr, 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 
)
extern

Definition at line 437 of file execGrouping.c.

439{
440 TupleHashEntry entry;
442
443 /* Need to run the hash functions in short-lived context */
445
446 /* set up data needed by hash and match functions */
447 hashtable->inputslot = slot;
448 hashtable->in_hash_expr = hashtable->tab_hash_expr;
449 hashtable->cur_eq_func = hashtable->tab_eq_func;
450
451 entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, hash);
452 Assert(entry == NULL || entry->hash == hash);
453
455
456 return entry;
457}

References Assert, TupleHashTableData::cur_eq_func, fb(), hash(), TupleHashEntryData::hash, TupleHashTableData::in_hash_expr, TupleHashTableData::inputslot, LookupTupleHashEntry_internal(), MemoryContextSwitchTo(), TupleHashTableData::tab_eq_func, TupleHashTableData::tab_hash_expr, and TupleHashTableData::tempcxt.

Referenced by agg_refill_hash_table().

◆ MakePerTupleExprContext()

ExprContext * MakePerTupleExprContext ( EState estate)
extern

Definition at line 458 of file execUtils.c.

459{
460 if (estate->es_per_tuple_exprcontext == NULL)
462
463 return estate->es_per_tuple_exprcontext;
464}

References CreateExprContext(), EState::es_per_tuple_exprcontext, and fb().

◆ MultiExecProcNode()

Node * MultiExecProcNode ( PlanState node)
extern

Definition at line 507 of file execProcnode.c.

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

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

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

◆ RegisterExprContextCallback()

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

Definition at line 963 of file execUtils.c.

966{
968
969 /* Save the info in appropriate memory context */
972 sizeof(ExprContext_CB));
973
975 ecxt_callback->arg = arg;
976
977 /* link to front of list for appropriate execution order */
978 ecxt_callback->next = econtext->ecxt_callbacks;
979 econtext->ecxt_callbacks = ecxt_callback;
980}
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void * arg
ExprContextCallbackFunction function
Definition execnodes.h:242

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

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

◆ RelationFindDeletedTupleInfoByIndex()

bool RelationFindDeletedTupleInfoByIndex ( Relation  rel,
Oid  idxoid,
TupleTableSlot searchslot,
TransactionId  oldestxmin,
TransactionId delete_xid,
ReplOriginId delete_origin,
TimestampTz delete_time 
)
extern

Definition at line 631 of file execReplication.c.

637{
640 int skey_attoff;
641 IndexScanDesc scan;
646
647 Assert(equalTupleDescs(desc, searchslot->tts_tupleDescriptor));
649
651 *delete_time = 0;
653
655
657
659
660 /* Build scan key. */
662
663 /*
664 * Start an index scan using SnapshotAny to identify dead tuples that are
665 * not visible under a standard MVCC snapshot. Tuples from transactions
666 * not yet committed or those just committed prior to the scan are
667 * excluded in update_most_recent_deletion_info().
668 */
670
671 index_rescan(scan, skey, skey_attoff, NULL, 0);
672
673 /* Try to find the tuple */
675 {
676 /*
677 * Avoid expensive equality check if the index is primary key or
678 * replica identity index.
679 */
681 {
682 if (eq == NULL)
683 eq = palloc0_array(TypeCacheEntry *, scanslot->tts_tupleDescriptor->natts);
684
686 continue;
687 }
688
691 }
692
693 index_endscan(scan);
694
696
698
699 return *delete_time != 0;
700}
static bool tuples_equal(TupleTableSlot *slot1, TupleTableSlot *slot2, TypeCacheEntry **eq, Bitmapset *columns)
static int build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel, TupleTableSlot *searchslot)
static void update_most_recent_deletion_info(TupleTableSlot *scanslot, TransactionId oldestxmin, TransactionId *delete_xid, TimestampTz *delete_time, ReplOriginId *delete_origin)
bool index_getnext_slot(IndexScanDesc scan, ScanDirection direction, TupleTableSlot *slot)
Definition indexam.c:730
IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, IndexScanInstrumentation *instrument, int nkeys, int norderbys)
Definition indexam.c:256
void index_endscan(IndexScanDesc scan)
Definition indexam.c:392
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition indexam.c:366
#define InvalidReplOriginId
Definition origin.h:33
Oid GetRelationIdentityOrPK(Relation rel)
Definition relation.c:905
#define InvalidTransactionId
Definition transam.h:31
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition tupdesc.c:590

References Assert, build_replindex_scan_key(), equalTupleDescs(), ExecDropSingleTupleTableSlot(), fb(), ForwardScanDirection, GetRelationIdentityOrPK(), index_beginscan(), index_close(), index_endscan(), index_getnext_slot(), INDEX_MAX_KEYS, index_open(), index_rescan(), InvalidReplOriginId, InvalidTransactionId, NoLock, OidIsValid, palloc0_array, PG_USED_FOR_ASSERTS_ONLY, RelationGetDescr, RowExclusiveLock, SnapshotAny, table_slot_create(), tuples_equal(), and update_most_recent_deletion_info().

Referenced by FindDeletedTupleInLocalRel().

◆ RelationFindDeletedTupleInfoSeq()

bool RelationFindDeletedTupleInfoSeq ( Relation  rel,
TupleTableSlot searchslot,
TransactionId  oldestxmin,
TransactionId delete_xid,
ReplOriginId delete_origin,
TimestampTz delete_time 
)
extern

Definition at line 562 of file execReplication.c.

567{
569 TableScanDesc scan;
573
574 Assert(equalTupleDescs(desc, searchslot->tts_tupleDescriptor));
575
578 *delete_time = 0;
579
580 /*
581 * If the relation has a replica identity key or a primary key that is
582 * unusable for locating deleted tuples (see
583 * IsIndexUsableForFindingDeletedTuple), a full table scan becomes
584 * necessary. In such cases, comparing the entire tuple is not required,
585 * since the remote tuple might not include all column values. Instead,
586 * the indexed columns alone are sufficient to identify the target tuple
587 * (see logicalrep_rel_mark_updatable).
588 */
591
592 /* fallback to PK if no replica identity */
593 if (!indexbitmap)
596
597 eq = palloc0_array(TypeCacheEntry *, searchslot->tts_tupleDescriptor->natts);
598
599 /*
600 * Start a heap scan using SnapshotAny to identify dead tuples that are
601 * not visible under a standard MVCC snapshot. Tuples from transactions
602 * not yet committed or those just committed prior to the scan are
603 * excluded in update_most_recent_deletion_info().
604 */
605 scan = table_beginscan(rel, SnapshotAny, 0, NULL);
607
608 table_rescan(scan, NULL);
609
610 /* Try to find the tuple */
612 {
614 continue;
615
618 }
619
620 table_endscan(scan);
622
623 return *delete_time != 0;
624}
@ INDEX_ATTR_BITMAP_PRIMARY_KEY
Definition relcache.h:70
@ INDEX_ATTR_BITMAP_IDENTITY_KEY
Definition relcache.h:71
static void table_endscan(TableScanDesc scan)
Definition tableam.h:1005
static void table_rescan(TableScanDesc scan, ScanKeyData *key)
Definition tableam.h:1014
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition tableam.h:1040
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key)
Definition tableam.h:897

References Assert, equalTupleDescs(), ExecDropSingleTupleTableSlot(), fb(), ForwardScanDirection, INDEX_ATTR_BITMAP_IDENTITY_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, InvalidReplOriginId, InvalidTransactionId, palloc0_array, PG_USED_FOR_ASSERTS_ONLY, RelationGetDescr, RelationGetIndexAttrBitmap(), SnapshotAny, table_beginscan(), table_endscan(), table_rescan(), table_scan_getnextslot(), table_slot_create(), tuples_equal(), and update_most_recent_deletion_info().

Referenced by FindDeletedTupleInLocalRel().

◆ RelationFindReplTupleByIndex()

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

Definition at line 182 of file execReplication.c.

186{
188 int skey_attoff;
189 IndexScanDesc scan;
193 bool found;
196
197 /* Open the index. */
199
201
203
204 /* Build scan key. */
206
207 /* Start an index scan. */
208 scan = index_beginscan(rel, idxrel, &snap, NULL, skey_attoff, 0);
209
210retry:
211 found = false;
212
213 index_rescan(scan, skey, skey_attoff, NULL, 0);
214
215 /* Try to find the tuple */
217 {
218 /*
219 * Avoid expensive equality check if the index is primary key or
220 * replica identity index.
221 */
223 {
224 if (eq == NULL)
225 eq = palloc0_array(TypeCacheEntry *, outslot->tts_tupleDescriptor->natts);
226
228 continue;
229 }
230
232
234 snap.xmin : snap.xmax;
235
236 /*
237 * If the tuple is locked, wait for locking transaction to finish and
238 * retry.
239 */
241 {
243 goto retry;
244 }
245
246 /* Found our tuple and it's not locked */
247 found = true;
248 break;
249 }
250
251 /* Found tuple, try to lock it in the lockmode. */
252 if (found)
253 {
254 TM_FailureData tmfd;
255 TM_Result res;
256
258
259 res = table_tuple_lock(rel, &(outslot->tts_tid), GetActiveSnapshot(),
260 outslot,
261 GetCurrentCommandId(false),
262 lockmode,
264 0 /* don't follow updates */ ,
265 &tmfd);
266
268
269 if (should_refetch_tuple(res, &tmfd))
270 goto retry;
271 }
272
273 index_endscan(scan);
274
275 /* Don't release lock until commit. */
277
278 return found;
279}
uint32 TransactionId
Definition c.h:666
static bool should_refetch_tuple(TM_Result res, TM_FailureData *tmfd)
void XactLockTableWait(TransactionId xid, Relation rel, const ItemPointerData *ctid, XLTW_Oper oper)
Definition lmgr.c:663
@ XLTW_None
Definition lmgr.h:26
@ LockWaitBlock
Definition lockoptions.h:39
Snapshot GetLatestSnapshot(void)
Definition snapmgr.c:354
void PushActiveSnapshot(Snapshot snapshot)
Definition snapmgr.c:682
void PopActiveSnapshot(void)
Definition snapmgr.c:775
Snapshot GetActiveSnapshot(void)
Definition snapmgr.c:800
#define InitDirtySnapshot(snapshotdata)
Definition snapmgr.h:42
TM_Result
Definition tableam.h:73
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:1571
#define TransactionIdIsValid(xid)
Definition transam.h:41
CommandId GetCurrentCommandId(bool used)
Definition xact.c:830

References build_replindex_scan_key(), ExecMaterializeSlot(), fb(), ForwardScanDirection, GetActiveSnapshot(), GetCurrentCommandId(), GetLatestSnapshot(), GetRelationIdentityOrPK(), index_beginscan(), index_close(), index_endscan(), index_getnext_slot(), INDEX_MAX_KEYS, index_open(), index_rescan(), InitDirtySnapshot, LockWaitBlock, NoLock, palloc0_array, PopActiveSnapshot(), PushActiveSnapshot(), RowExclusiveLock, should_refetch_tuple(), table_tuple_lock(), TransactionIdIsValid, tuples_equal(), XactLockTableWait(), and XLTW_None.

Referenced by FindReplTupleInLocalRel().

◆ RelationFindReplTupleSeq()

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

Definition at line 369 of file execReplication.c.

371{
373 TableScanDesc scan;
377 bool found;
379
380 Assert(equalTupleDescs(desc, outslot->tts_tupleDescriptor));
381
382 eq = palloc0_array(TypeCacheEntry *, outslot->tts_tupleDescriptor->natts);
383
384 /* Start a heap scan. */
386 scan = table_beginscan(rel, &snap, 0, NULL);
388
389retry:
390 found = false;
391
392 table_rescan(scan, NULL);
393
394 /* Try to find the tuple */
396 {
398 continue;
399
400 found = true;
402
404 snap.xmin : snap.xmax;
405
406 /*
407 * If the tuple is locked, wait for locking transaction to finish and
408 * retry.
409 */
411 {
413 goto retry;
414 }
415
416 /* Found our tuple and it's not locked */
417 break;
418 }
419
420 /* Found tuple, try to lock it in the lockmode. */
421 if (found)
422 {
423 TM_FailureData tmfd;
424 TM_Result res;
425
427
428 res = table_tuple_lock(rel, &(outslot->tts_tid), GetActiveSnapshot(),
429 outslot,
430 GetCurrentCommandId(false),
431 lockmode,
433 0 /* don't follow updates */ ,
434 &tmfd);
435
437
438 if (should_refetch_tuple(res, &tmfd))
439 goto retry;
440 }
441
442 table_endscan(scan);
444
445 return found;
446}

References Assert, equalTupleDescs(), ExecCopySlot(), ExecDropSingleTupleTableSlot(), fb(), ForwardScanDirection, GetActiveSnapshot(), GetCurrentCommandId(), GetLatestSnapshot(), InitDirtySnapshot, LockWaitBlock, palloc0_array, PG_USED_FOR_ASSERTS_ONLY, PopActiveSnapshot(), PushActiveSnapshot(), RelationGetDescr, should_refetch_tuple(), table_beginscan(), table_endscan(), table_rescan(), table_scan_getnextslot(), table_slot_create(), table_tuple_lock(), TransactionIdIsValid, tuples_equal(), XactLockTableWait(), and XLTW_None.

Referenced by FindReplTupleInLocalRel().

◆ ReScanExprContext()

void ReScanExprContext ( ExprContext econtext)
extern

Definition at line 443 of file execUtils.c.

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

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

◆ standard_ExecutorEnd()

void standard_ExecutorEnd ( QueryDesc queryDesc)
extern

Definition at line 475 of file execMain.c.

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

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

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

◆ standard_ExecutorFinish()

void standard_ExecutorFinish ( QueryDesc queryDesc)
extern

Definition at line 415 of file execMain.c.

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

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(), fb(), 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 
)
extern

Definition at line 307 of file execMain.c.

309{
310 EState *estate;
311 CmdType operation;
313 bool sendTuples;
314 MemoryContext oldcontext;
315
316 /* sanity checks */
317 Assert(queryDesc != NULL);
318
319 estate = queryDesc->estate;
320
321 Assert(estate != NULL);
323
324 /* caller must ensure the query's snapshot is active */
326
327 /*
328 * Switch into per-query memory context
329 */
330 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
331
332 /* Allow instrumentation of Executor overall runtime */
333 if (queryDesc->totaltime)
334 InstrStartNode(queryDesc->totaltime);
335
336 /*
337 * extract information from the query descriptor and the query feature.
338 */
339 operation = queryDesc->operation;
340 dest = queryDesc->dest;
341
342 /*
343 * startup tuple receiver, if we will be emitting tuples
344 */
345 estate->es_processed = 0;
346
347 sendTuples = (operation == CMD_SELECT ||
348 queryDesc->plannedstmt->hasReturning);
349
350 if (sendTuples)
351 dest->rStartup(dest, operation, queryDesc->tupDesc);
352
353 /*
354 * Run plan, unless direction is NoMovement.
355 *
356 * Note: pquery.c selects NoMovement if a prior call already reached
357 * end-of-data in the user-specified fetch direction. This is important
358 * because various parts of the executor can misbehave if called again
359 * after reporting EOF. For example, heapam.c would actually restart a
360 * heapscan and return all its data afresh. There is also some doubt
361 * about whether a parallel plan would operate properly if an additional,
362 * necessarily non-parallel execution request occurs after completing a
363 * parallel execution. (That case should work, but it's untested.)
364 */
365 if (!ScanDirectionIsNoMovement(direction))
366 ExecutePlan(queryDesc,
367 operation,
369 count,
370 direction,
371 dest);
372
373 /*
374 * Update es_total_processed to keep track of the number of tuples
375 * processed across multiple ExecutorRun() calls.
376 */
377 estate->es_total_processed += estate->es_processed;
378
379 /*
380 * shutdown tuple receiver, if we started it
381 */
382 if (sendTuples)
383 dest->rShutdown(dest);
384
385 if (queryDesc->totaltime)
386 InstrStopNode(queryDesc->totaltime, estate->es_processed);
387
388 MemoryContextSwitchTo(oldcontext);
389}
static void ExecutePlan(QueryDesc *queryDesc, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, DestReceiver *dest)
Definition execMain.c:1660
CmdType
Definition nodes.h:273
#define ScanDirectionIsNoMovement(direction)
Definition sdir.h:57
bool hasReturning
Definition plannodes.h:80
DestReceiver * dest
Definition execdesc.h:41

References Assert, CMD_SELECT, QueryDesc::dest, 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(), fb(), GetActiveSnapshot(), PlannedStmt::hasReturning, InstrStartNode(), InstrStopNode(), MemoryContextSwitchTo(), QueryDesc::operation, QueryDesc::plannedstmt, ScanDirectionIsNoMovement, QueryDesc::totaltime, and QueryDesc::tupDesc.

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

◆ standard_ExecutorStart()

void standard_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)
extern

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
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:802
static void InitPlan(QueryDesc *queryDesc, int eflags)
Definition execMain.c:836
EState * CreateExecutorState(void)
Definition execUtils.c:88
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition snapmgr.c:824
bool hasModifyingCTE
Definition plannodes.h:83
List * rowMarks
Definition plannodes.h:138
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:5115
bool XactReadOnly
Definition xact.c:83
bool IsInParallelMode(void)
Definition xact.c:1090

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(), fb(), GetActiveSnapshot(), GetCurrentCommandId(), PlannedStmt::hasModifyingCTE, InitPlan(), QueryDesc::instrument_options, IsInParallelMode(), PlannedStmt::jitFlags, list_length(), MemoryContextSwitchTo(), NIL, QueryDesc::operation, palloc0_array, 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().

◆ TupleHashEntryGetAdditional()

static void * TupleHashEntryGetAdditional ( TupleHashTable  hashtable,
TupleHashEntry  entry 
)
inlinestatic

Definition at line 192 of file executor.h.

193{
194 if (hashtable->additionalsize > 0)
195 return (char *) entry->firstTuple - hashtable->additionalsize;
196 else
197 return NULL;
198}
MinimalTuple firstTuple
Definition execnodes.h:857

References TupleHashTableData::additionalsize, fb(), and TupleHashEntryData::firstTuple.

Referenced by agg_refill_hash_table(), agg_retrieve_hash_table_in_memory(), initialize_hash_entry(), lookup_hash_entries(), setop_fill_hash_table(), and setop_retrieve_hash_table().

◆ TupleHashEntryGetTuple()

static MinimalTuple TupleHashEntryGetTuple ( TupleHashEntry  entry)
inlinestatic

Definition at line 178 of file executor.h.

179{
180 return entry->firstTuple;
181}

References TupleHashEntryData::firstTuple.

Referenced by agg_retrieve_hash_table_in_memory(), findPartialMatch(), and setop_retrieve_hash_table().

◆ TupleHashEntrySize()

static size_t TupleHashEntrySize ( void  )
inlinestatic

Definition at line 169 of file executor.h.

170{
171 return sizeof(TupleHashEntryData);
172}

Referenced by build_hash_tables(), hash_agg_entry_size(), and hash_agg_update_metrics().

◆ TupleHashTableHash()

uint32 TupleHashTableHash ( TupleHashTable  hashtable,
TupleTableSlot slot 
)
extern

Definition at line 414 of file execGrouping.c.

415{
417 uint32 hash;
418
419 hashtable->inputslot = slot;
420 hashtable->in_hash_expr = hashtable->tab_hash_expr;
421
422 /* Need to run the hash functions in short-lived context */
424
426
428
429 return hash;
430}

References fb(), hash(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_expr, TupleHashTableData::inputslot, MemoryContextSwitchTo(), TupleHashTableData::tab_hash_expr, TupleHashTableData::tempcxt, and TupleHashTableHash_internal().

◆ UnregisterExprContextCallback()

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

Definition at line 989 of file execUtils.c.

992{
995
996 prev_callback = &econtext->ecxt_callbacks;
997
998 while ((ecxt_callback = *prev_callback) != NULL)
999 {
1000 if (ecxt_callback->function == function && ecxt_callback->arg == arg)
1001 {
1004 }
1005 else
1007 }
1008}
struct ExprContext_CB * next
Definition execnodes.h:241

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

Referenced by end_MultiFuncCall(), and fmgr_sql().

◆ UpdateChangedParamSet()

void UpdateChangedParamSet ( PlanState node,
Bitmapset newchg 
)
extern

Definition at line 910 of file execUtils.c.

911{
913
914 /*
915 * The plan node only depends on params listed in its allParam set. Don't
916 * include anything else into its chgParam set.
917 */
919 node->chgParam = bms_join(node->chgParam, parmset);
920}
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:292
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition bitmapset.c:1229
Bitmapset * allParam
Definition plannodes.h:250

References Plan::allParam, bms_intersect(), bms_join(), PlanState::chgParam, fb(), 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 74 of file execMain.c.

Referenced by _PG_init(), and ExecCheckPermissions().

◆ ExecutorEnd_hook

PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook
extern

Definition at line 71 of file execMain.c.

Referenced by _PG_init(), and ExecutorEnd().

◆ ExecutorFinish_hook

PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook
extern

Definition at line 70 of file execMain.c.

Referenced by _PG_init(), and ExecutorFinish().

◆ ExecutorRun_hook

PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook
extern

Definition at line 69 of file execMain.c.

Referenced by _PG_init(), and ExecutorRun().

◆ ExecutorStart_hook

PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook
extern

Definition at line 68 of file execMain.c.

Referenced by _PG_init(), and ExecutorStart().