PostgreSQL Source Code git master
Loading...
Searching...
No Matches
executor.h File Reference
#include "access/xlogdefs.h"
#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)
 
#define EIIT_IS_UPDATE   (1<<0)
 
#define EIIT_NO_DUPE_ERROR   (1<<1)
 
#define EIIT_ONLY_SUMMARIZING   (1<<2)
 

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)
 
ExprStateExecInitExprWithContext (Expr *node, PlanState *parent, Node *escontext)
 
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)
 
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)
 
ExprStateExecPrepareExprWithContext (Expr *node, EState *estate, Node *escontext)
 
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, uint16 flags)
 
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, EState *estate, bits32 options, TupleTableSlot *slot, List *arbiterIndexes, bool *specConflict)
 
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:342
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static int fb(int x)
text * cstring_to_text(const char *s)
Definition varlena.c:184

Definition at line 632 of file executor.h.

633 { \
634 Datum values_[1]; \
635 bool isnull_[1]; \
637 isnull_[0] = false; \
640 } while (0)

◆ EIIT_IS_UPDATE

#define EIIT_IS_UPDATE   (1<<0)

Definition at line 748 of file executor.h.

◆ EIIT_NO_DUPE_ERROR

#define EIIT_NO_DUPE_ERROR   (1<<1)

Definition at line 749 of file executor.h.

◆ EIIT_ONLY_SUMMARIZING

#define EIIT_ONLY_SUMMARIZING   (1<<2)

Definition at line 750 of file executor.h.

◆ EvalPlanQualSetSlot

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

Definition at line 290 of file executor.h.

◆ EXEC_FLAG_BACKWARD

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

Definition at line 70 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_GENERIC

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

Definition at line 68 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_ONLY

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

Definition at line 67 of file executor.h.

◆ EXEC_FLAG_MARK

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

Definition at line 71 of file executor.h.

◆ EXEC_FLAG_REWIND

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

Definition at line 69 of file executor.h.

◆ EXEC_FLAG_SKIP_TRIGGERS

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

Definition at line 72 of file executor.h.

◆ EXEC_FLAG_WITH_NO_DATA

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

Definition at line 73 of file executor.h.

◆ GetPerTupleExprContext

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

Definition at line 660 of file executor.h.

662 : \

◆ GetPerTupleMemoryContext

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

Definition at line 665 of file executor.h.

◆ ResetExprContext

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

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

670 { \
671 if ((estate)->es_per_tuple_exprcontext) \
672 ResetExprContext((estate)->es_per_tuple_exprcontext); \
673 } while (0)

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 582 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 583 of file executor.h.

◆ ExecutorCheckPerms_hook_type

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

Definition at line 95 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 91 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 87 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 81 of file executor.h.

◆ ExecutorStart_hook_type

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

Definition at line 77 of file executor.h.

◆ Path

typedef struct Path Path

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

2528{
2530
2532
2533 tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2534 tstate->dest = dest;
2535
2536 tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2537
2538 return tstate;
2539}
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:117
#define MAXALIGN(LEN)
Definition c.h:898
#define PG_UINT32_MAX
Definition c.h:676
#define Assert(condition)
Definition c.h:945
uint32_t uint32
Definition c.h:618
ExprState * ExecBuildHash32FromAttrs(TupleDesc desc, const TupleTableSlotOps *ops, FmgrInfo *hashfunctions, Oid *collations, int numCols, AttrNumber *keyColIdx, PlanState *parent, uint32 init_value)
Definition execExpr.c:4168
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:4494
const TupleTableSlotOps TTSOpsMinimalTuple
Definition execTuples.c:86
ExprContext * CreateStandaloneExprContext(void)
Definition execUtils.c:362
static uint32 murmurhash32(uint32 data)
Definition hashfn.h:92
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
AttrNumber * keyColIdx
Definition execnodes.h:884
tuplehash_hash * hashtab
Definition execnodes.h:882
ExprState * in_hash_expr
Definition execnodes.h:894
ExprState * tab_hash_expr
Definition execnodes.h:885
MemoryContext tempcxt
Definition execnodes.h:889
ExprState * tab_eq_func
Definition execnodes.h:886
TupleTableSlot * tableslot
Definition execnodes.h:891
ExprContext * exprcontext
Definition execnodes.h:896
TupleTableSlot * inputslot
Definition execnodes.h:893
ExprState * cur_eq_func
Definition execnodes.h:895
MemoryContext tuplescxt
Definition execnodes.h:888
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:242

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

966{
968 values, isnull,
969 estate, newIndex,
970 CEOUC_WAIT, false, NULL);
971}
static Datum values[MAXATTR]
Definition bootstrap.c:188
@ 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 1025 of file execReplication.c.

1026{
1028
1029 /*
1030 * Skip checking the replica identity for partitioned tables, because the
1031 * operations are actually performed on the leaf partitions.
1032 */
1033 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1034 return;
1035
1036 /* We only need to do checks for UPDATE and DELETE. */
1037 if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
1038 return;
1039
1040 /*
1041 * It is only safe to execute UPDATE/DELETE if the relation does not
1042 * publish UPDATEs or DELETEs, or all the following conditions are
1043 * satisfied:
1044 *
1045 * 1. All columns, referenced in the row filters from publications which
1046 * the relation is in, are valid - i.e. when all referenced columns are
1047 * part of REPLICA IDENTITY.
1048 *
1049 * 2. All columns, referenced in the column lists are valid - i.e. when
1050 * all columns referenced in the REPLICA IDENTITY are covered by the
1051 * column list.
1052 *
1053 * 3. All generated columns in REPLICA IDENTITY of the relation, are valid
1054 * - i.e. when all these generated columns are published.
1055 *
1056 * XXX We could optimize it by first checking whether any of the
1057 * publications have a row filter or column list for this relation, or if
1058 * the relation contains a generated column. If none of these exist and
1059 * the relation has replica identity then we can avoid building the
1060 * descriptor but as this happens only one time it doesn't seem worth the
1061 * additional complexity.
1062 */
1064 if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
1065 ereport(ERROR,
1067 errmsg("cannot update table \"%s\"",
1069 errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
1070 else if (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
1071 ereport(ERROR,
1073 errmsg("cannot update table \"%s\"",
1075 errdetail("Column list used by the publication does not cover the replica identity.")));
1076 else if (cmd == CMD_UPDATE && !pubdesc.gencols_valid_for_update)
1077 ereport(ERROR,
1079 errmsg("cannot update table \"%s\"",
1081 errdetail("Replica identity must not contain unpublished generated columns.")));
1082 else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
1083 ereport(ERROR,
1085 errmsg("cannot delete from table \"%s\"",
1087 errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
1088 else if (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
1089 ereport(ERROR,
1091 errmsg("cannot delete from table \"%s\"",
1093 errdetail("Column list used by the publication does not cover the replica identity.")));
1094 else if (cmd == CMD_DELETE && !pubdesc.gencols_valid_for_delete)
1095 ereport(ERROR,
1097 errmsg("cannot delete from table \"%s\"",
1099 errdetail("Replica identity must not contain unpublished generated columns.")));
1100
1101 /* If relation has replica identity we are always good. */
1103 return;
1104
1105 /* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */
1106 if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
1107 return;
1108
1109 /*
1110 * This is UPDATE/DELETE and there is no replica identity.
1111 *
1112 * Check if the table publishes UPDATES or DELETES.
1113 */
1114 if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
1115 ereport(ERROR,
1117 errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
1119 errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
1120 else if (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
1121 ereport(ERROR,
1123 errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
1125 errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
1126}
#define OidIsValid(objectId)
Definition c.h:860
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#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
static char * errmsg
#define RelationGetRelationName(relation)
Definition rel.h:548
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Definition relcache.c:5784
Oid RelationGetReplicaIndex(Relation relation)
Definition relcache.c:5062
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 1136 of file execReplication.c.

1138{
1142 ereport(ERROR,
1144 errmsg("cannot use relation \"%s.%s\" as logical replication target",
1145 nspname, relname),
1147
1148 /*
1149 * Allow RELKIND_RELATION and RELKIND_PARTITIONED_TABLE to be treated
1150 * interchangeably, but ensure that sequences (RELKIND_SEQUENCE) match
1151 * exactly on both publisher and subscriber.
1152 */
1155 ereport(ERROR,
1157 /* translator: 3rd and 4th %s are "sequence" or "table" */
1158 errmsg("relation \"%s.%s\" type mismatch: source \"%s\", target \"%s\"",
1159 nspname, relname,
1160 remoterelkind == RELKIND_SEQUENCE ? "sequence" : "table",
1161 localrelkind == RELKIND_SEQUENCE ? "sequence" : "table"));
1162}
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
NameData relname
Definition pg_class.h:40

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 1056 of file execMain.c.

1058{
1059 Relation resultRel = resultRelInfo->ri_RelationDesc;
1060 FdwRoutine *fdwroutine;
1061
1062 /* Expect a fully-formed ResultRelInfo from InitResultRelInfo(). */
1063 Assert(resultRelInfo->ri_needLockTagTuple ==
1064 IsInplaceUpdateRelation(resultRel));
1065
1066 switch (resultRel->rd_rel->relkind)
1067 {
1068 case RELKIND_RELATION:
1070
1071 /*
1072 * For MERGE, check that the target relation supports each action.
1073 * For other operations, just check the operation itself.
1074 */
1075 if (operation == CMD_MERGE)
1077 CheckCmdReplicaIdentity(resultRel, action->commandType);
1078 else
1079 CheckCmdReplicaIdentity(resultRel, operation);
1080
1081 /*
1082 * For INSERT ON CONFLICT DO UPDATE, additionally check that the
1083 * target relation supports UPDATE.
1084 */
1085 if (onConflictAction == ONCONFLICT_UPDATE)
1087 break;
1088 case RELKIND_SEQUENCE:
1089 ereport(ERROR,
1091 errmsg("cannot change sequence \"%s\"",
1092 RelationGetRelationName(resultRel))));
1093 break;
1094 case RELKIND_TOASTVALUE:
1095 ereport(ERROR,
1097 errmsg("cannot change TOAST relation \"%s\"",
1098 RelationGetRelationName(resultRel))));
1099 break;
1100 case RELKIND_VIEW:
1101
1102 /*
1103 * Okay only if there's a suitable INSTEAD OF trigger. Otherwise,
1104 * complain, but omit errdetail because we haven't got the
1105 * information handy (and given that it really shouldn't happen,
1106 * it's not worth great exertion to get).
1107 */
1108 if (!view_has_instead_trigger(resultRel, operation, mergeActions))
1109 error_view_not_updatable(resultRel, operation, mergeActions,
1110 NULL);
1111 break;
1112 case RELKIND_MATVIEW:
1114 ereport(ERROR,
1116 errmsg("cannot change materialized view \"%s\"",
1117 RelationGetRelationName(resultRel))));
1118 break;
1120 /* Okay only if the FDW supports it */
1121 fdwroutine = resultRelInfo->ri_FdwRoutine;
1122 switch (operation)
1123 {
1124 case CMD_INSERT:
1125 if (fdwroutine->ExecForeignInsert == NULL)
1126 ereport(ERROR,
1128 errmsg("cannot insert into foreign table \"%s\"",
1129 RelationGetRelationName(resultRel))));
1130 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1131 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1132 ereport(ERROR,
1134 errmsg("foreign table \"%s\" does not allow inserts",
1135 RelationGetRelationName(resultRel))));
1136 break;
1137 case CMD_UPDATE:
1138 if (fdwroutine->ExecForeignUpdate == NULL)
1139 ereport(ERROR,
1141 errmsg("cannot update foreign table \"%s\"",
1142 RelationGetRelationName(resultRel))));
1143 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1144 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1145 ereport(ERROR,
1147 errmsg("foreign table \"%s\" does not allow updates",
1148 RelationGetRelationName(resultRel))));
1149 break;
1150 case CMD_DELETE:
1151 if (fdwroutine->ExecForeignDelete == NULL)
1152 ereport(ERROR,
1154 errmsg("cannot delete from foreign table \"%s\"",
1155 RelationGetRelationName(resultRel))));
1156 if (fdwroutine->IsForeignRelUpdatable != NULL &&
1157 (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1158 ereport(ERROR,
1160 errmsg("foreign table \"%s\" does not allow deletes",
1161 RelationGetRelationName(resultRel))));
1162 break;
1163 default:
1164 elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1165 break;
1166 }
1167 break;
1168 case RELKIND_PROPGRAPH:
1169 ereport(ERROR,
1171 errmsg("cannot change property graph \"%s\"",
1172 RelationGetRelationName(resultRel))));
1173 break;
1174 default:
1175 ereport(ERROR,
1177 errmsg("cannot change relation \"%s\"",
1178 RelationGetRelationName(resultRel))));
1179 break;
1180 }
1181}
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:524
Relation ri_RelationDesc
Definition execnodes.h:492
struct FdwRoutine * ri_FdwRoutine
Definition execnodes.h:545

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 90 of file execUtils.c.

91{
92 EState *estate;
93 MemoryContext qcontext;
94 MemoryContext oldcontext;
95
96 /*
97 * Create the per-query context for this Executor run.
98 */
100 "ExecutorState",
102
103 /*
104 * Make the EState node within the per-query context. This way, we don't
105 * need a separate pfree() operation for it at shutdown.
106 */
107 oldcontext = MemoryContextSwitchTo(qcontext);
108
109 estate = makeNode(EState);
110
111 /*
112 * Initialize all fields of the Executor State structure
113 */
115 estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
116 estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
117 estate->es_range_table = NIL;
118 estate->es_range_table_size = 0;
119 estate->es_relations = NULL;
120 estate->es_rowmarks = NULL;
121 estate->es_rteperminfos = NIL;
122 estate->es_plannedstmt = NULL;
123 estate->es_part_prune_infos = NIL;
124 estate->es_part_prune_states = NIL;
125 estate->es_part_prune_results = NIL;
126 estate->es_unpruned_relids = NULL;
127
128 estate->es_junkFilter = NULL;
129
130 estate->es_output_cid = (CommandId) 0;
131
132 estate->es_result_relations = NULL;
136
139
140 estate->es_param_list_info = NULL;
141 estate->es_param_exec_vals = NULL;
142
143 estate->es_queryEnv = NULL;
144
145 estate->es_query_cxt = qcontext;
146
147 estate->es_tupleTable = NIL;
148
149 estate->es_processed = 0;
150 estate->es_total_processed = 0;
151
152 estate->es_top_eflags = 0;
153 estate->es_instrument = 0;
154 estate->es_finished = false;
155
156 estate->es_exprcontexts = NIL;
157
158 estate->es_subplanstates = NIL;
159
160 estate->es_auxmodifytables = NIL;
161
163
164 estate->es_sourceText = NULL;
165
166 estate->es_use_parallel_mode = false;
169
170 estate->es_jit_flags = 0;
171 estate->es_jit = NULL;
172
173 /*
174 * Return the executor state structure
175 */
176 MemoryContextSwitchTo(oldcontext);
177
178 return estate;
179}
uint32 CommandId
Definition c.h:752
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:726
List * es_part_prune_infos
Definition execnodes.h:682
int es_parallel_workers_to_launch
Definition execnodes.h:758
List * es_tuple_routing_result_relations
Definition execnodes.h:710
int es_top_eflags
Definition execnodes.h:731
struct JitContext * es_jit
Definition execnodes.h:776
int es_instrument
Definition execnodes.h:732
PlannedStmt * es_plannedstmt
Definition execnodes.h:681
QueryEnvironment * es_queryEnv
Definition execnodes.h:719
ResultRelInfo ** es_result_relations
Definition execnodes.h:697
ParamExecData * es_param_exec_vals
Definition execnodes.h:717
uint64 es_total_processed
Definition execnodes.h:728
List * es_range_table
Definition execnodes.h:674
List * es_rteperminfos
Definition execnodes.h:680
Bitmapset * es_unpruned_relids
Definition execnodes.h:685
List * es_part_prune_states
Definition execnodes.h:683
List * es_exprcontexts
Definition execnodes.h:735
ParamListInfo es_param_list_info
Definition execnodes.h:716
ExecRowMark ** es_rowmarks
Definition execnodes.h:678
bool es_finished
Definition execnodes.h:733
List * es_insert_pending_result_relations
Definition execnodes.h:783
MemoryContext es_query_cxt
Definition execnodes.h:722
List * es_tupleTable
Definition execnodes.h:724
ScanDirection es_direction
Definition execnodes.h:671
List * es_trig_target_relations
Definition execnodes.h:713
int es_jit_flags
Definition execnodes.h:775
List * es_opened_result_relations
Definition execnodes.h:700
bool es_use_parallel_mode
Definition execnodes.h:756
Relation * es_relations
Definition execnodes.h:676
List * es_subplanstates
Definition execnodes.h:737
ExprContext * es_per_tuple_exprcontext
Definition execnodes.h:746
int es_parallel_workers_launched
Definition execnodes.h:760
CommandId es_output_cid
Definition execnodes.h:694
Index es_range_table_size
Definition execnodes.h:675
List * es_insert_pending_modifytables
Definition execnodes.h:784
const char * es_sourceText
Definition execnodes.h:689
Snapshot es_snapshot
Definition execnodes.h:672
List * es_auxmodifytables
Definition execnodes.h:739
JunkFilter * es_junkFilter
Definition execnodes.h:691
List * es_part_prune_results
Definition execnodes.h:684
Snapshot es_crosscheck_snapshot
Definition execnodes.h:673

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_part_prune_results, EState::es_part_prune_states, 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_unpruned_relids, 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 312 of file execUtils.c.

313{
315}
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition execUtils.c:242

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 362 of file execUtils.c.

363{
364 ExprContext *econtext;
365
366 /* Create the ExprContext node within the caller's memory context */
367 econtext = makeNode(ExprContext);
368
369 /* Initialize fields of ExprContext */
370 econtext->ecxt_scantuple = NULL;
371 econtext->ecxt_innertuple = NULL;
372 econtext->ecxt_outertuple = NULL;
373
375
376 /*
377 * Create working memory for expression evaluation in this context.
378 */
379 econtext->ecxt_per_tuple_memory =
381 "ExprContext",
383
384 econtext->ecxt_param_exec_vals = NULL;
385 econtext->ecxt_param_list_info = NULL;
386
387 econtext->ecxt_aggvalues = NULL;
388 econtext->ecxt_aggnulls = NULL;
389
390 econtext->caseValue_datum = (Datum) 0;
391 econtext->caseValue_isNull = true;
392
393 econtext->domainValue_datum = (Datum) 0;
394 econtext->domainValue_isNull = true;
395
396 econtext->ecxt_estate = NULL;
397
398 econtext->ecxt_callbacks = NULL;
399
400 return econtext;
401}
Datum domainValue_datum
Definition execnodes.h:315
ParamListInfo ecxt_param_list_info
Definition execnodes.h:296
MemoryContext ecxt_per_tuple_memory
Definition execnodes.h:292
TupleTableSlot * ecxt_innertuple
Definition execnodes.h:286
ParamExecData * ecxt_param_exec_vals
Definition execnodes.h:295
Datum * ecxt_aggvalues
Definition execnodes.h:303
bool caseValue_isNull
Definition execnodes.h:311
TupleTableSlot * ecxt_scantuple
Definition execnodes.h:284
Datum caseValue_datum
Definition execnodes.h:309
bool * ecxt_aggnulls
Definition execnodes.h:305
MemoryContext ecxt_per_query_memory
Definition execnodes.h:291
ExprContext_CB * ecxt_callbacks
Definition execnodes.h:329
bool domainValue_isNull
Definition execnodes.h:317
struct EState * ecxt_estate
Definition execnodes.h:326
TupleTableSlot * ecxt_outertuple
Definition execnodes.h:288

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 327 of file execUtils.c.

328{
329 Size maxBlockSize;
330
331 maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
332
333 /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
334 maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
335
336 /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
337 maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
338
340 ALLOCSET_DEFAULT_INITSIZE, maxBlockSize);
341}
#define Min(x, y)
Definition c.h:1093
#define Max(x, y)
Definition c.h:1087
size_t Size
Definition c.h:691
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 2573 of file execTuples.c.

2574{
2575 Datum values[1];
2576 bool isnull[1] = {false};
2577
2578 while (*txt)
2579 {
2580 const char *eol;
2581 int len;
2582
2583 eol = strchr(txt, '\n');
2584 if (eol)
2585 {
2586 len = eol - txt;
2587 eol++;
2588 }
2589 else
2590 {
2591 len = strlen(txt);
2592 eol = txt + len;
2593 }
2594
2596 do_tup_output(tstate, values, isnull);
2598 txt = eol;
2599 }
2600}
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:196

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 2545 of file execTuples.c.

2546{
2547 TupleTableSlot *slot = tstate->slot;
2548 int natts = slot->tts_tupleDescriptor->natts;
2549
2550 /* make sure the slot is clear */
2551 ExecClearTuple(slot);
2552
2553 /* insert data */
2554 memcpy(slot->tts_values, values, natts * sizeof(Datum));
2555 memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2556
2557 /* mark slot as containing a virtual tuple */
2559
2560 /* send the tuple to the receiver */
2561 (void) tstate->dest->receiveSlot(slot, tstate->dest);
2562
2563 /* clean up */
2564 ExecClearTuple(slot);
2565}
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
TupleDesc tts_tupleDescriptor
Definition tuptable.h:129
bool * tts_isnull
Definition tuptable.h:133
Datum * tts_values
Definition tuptable.h:131
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476

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 2603 of file execTuples.c.

2604{
2605 tstate->dest->rShutdown(tstate->dest);
2606 /* note that destroying the dest is not ours to do */
2608 pfree(tstate);
2609}
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 2668 of file execMain.c.

2670{
2671 TupleTableSlot *slot;
2673
2674 Assert(rti > 0);
2675
2676 /*
2677 * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2678 */
2679 EvalPlanQualBegin(epqstate);
2680
2681 /*
2682 * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
2683 * an unnecessary copy.
2684 */
2685 testslot = EvalPlanQualSlot(epqstate, relation, rti);
2686 if (testslot != inputslot)
2687 ExecCopySlot(testslot, inputslot);
2688
2689 /*
2690 * Mark that an EPQ tuple is available for this relation. (If there is
2691 * more than one result relation, the others remain marked as having no
2692 * tuple available.)
2693 */
2694 epqstate->relsubs_done[rti - 1] = false;
2695 epqstate->relsubs_blocked[rti - 1] = false;
2696
2697 /*
2698 * Run the EPQ query. We assume it will return at most one tuple.
2699 */
2700 slot = EvalPlanQualNext(epqstate);
2701
2702 /*
2703 * If we got a tuple, force the slot to materialize the tuple so that it
2704 * is not dependent on any local state in the EPQ query (in particular,
2705 * it's highly likely that the slot contains references to any pass-by-ref
2706 * datums that may be present in copyTuple). As with the next step, this
2707 * is to guard against early re-use of the EPQ query.
2708 */
2709 if (!TupIsNull(slot))
2710 ExecMaterializeSlot(slot);
2711
2712 /*
2713 * Clear out the test tuple, and mark that no tuple is available here.
2714 * This is needed in case the EPQ state is re-used to test a tuple for a
2715 * different target relation.
2716 */
2718 epqstate->relsubs_blocked[rti - 1] = true;
2719
2720 return slot;
2721}
TupleTableSlot * EvalPlanQualSlot(EPQState *epqstate, Relation relation, Index rti)
Definition execMain.c:2795
void EvalPlanQualBegin(EPQState *epqstate)
Definition execMain.c:2950
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition execMain.c:2934
bool * relsubs_blocked
Definition execnodes.h:1368
bool * relsubs_done
Definition execnodes.h:1359
#define TupIsNull(slot)
Definition tuptable.h:325
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition tuptable.h:543
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition tuptable.h:494

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 2950 of file execMain.c.

2951{
2952 EState *parentestate = epqstate->parentestate;
2953 EState *recheckestate = epqstate->recheckestate;
2954
2955 if (recheckestate == NULL)
2956 {
2957 /* First time through, so create a child EState */
2958 EvalPlanQualStart(epqstate, epqstate->plan);
2959 }
2960 else
2961 {
2962 /*
2963 * We already have a suitable child EPQ tree, so just reset it.
2964 */
2965 Index rtsize = parentestate->es_range_table_size;
2967
2968 /*
2969 * Reset the relsubs_done[] flags to equal relsubs_blocked[], so that
2970 * the EPQ run will never attempt to fetch tuples from blocked target
2971 * relations.
2972 */
2973 memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
2974 rtsize * sizeof(bool));
2975
2976 /* Recopy current values of parent parameters */
2977 if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2978 {
2979 int i;
2980
2981 /*
2982 * Force evaluation of any InitPlan outputs that could be needed
2983 * by the subplan, just in case they got reset since
2984 * EvalPlanQualStart (see comments therein).
2985 */
2986 ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2987 GetPerTupleExprContext(parentestate));
2988
2989 i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2990
2991 while (--i >= 0)
2992 {
2993 /* copy value if any, but not execPlan link */
2994 recheckestate->es_param_exec_vals[i].value =
2995 parentestate->es_param_exec_vals[i].value;
2996 recheckestate->es_param_exec_vals[i].isnull =
2997 parentestate->es_param_exec_vals[i].isnull;
2998 }
2999 }
3000
3001 /*
3002 * Mark child plan tree as needing rescan at all scan nodes. The
3003 * first ExecProcNode will take care of actually doing the rescan.
3004 */
3005 rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
3006 epqstate->epqParam);
3007 }
3008}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
unsigned int Index
Definition c.h:700
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition execMain.c:3017
#define GetPerTupleExprContext(estate)
Definition executor.h:660
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:1331
int epqParam
Definition execnodes.h:1314
EState * parentestate
Definition execnodes.h:1313
EState * recheckestate
Definition execnodes.h:1345
PlanState * recheckplanstate
Definition execnodes.h:1370
bool isnull
Definition params.h:149
Datum value
Definition params.h:148
List * paramExecTypes
Definition plannodes.h:148

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 3198 of file execMain.c.

3199{
3200 EState *estate = epqstate->recheckestate;
3201 Index rtsize;
3202 MemoryContext oldcontext;
3203 ListCell *l;
3204
3206
3207 /*
3208 * We may have a tuple table, even if EPQ wasn't started, because we allow
3209 * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
3210 */
3211 if (epqstate->tuple_table != NIL)
3212 {
3213 memset(epqstate->relsubs_slot, 0,
3214 rtsize * sizeof(TupleTableSlot *));
3215 ExecResetTupleTable(epqstate->tuple_table, true);
3216 epqstate->tuple_table = NIL;
3217 }
3218
3219 /* EPQ wasn't started, nothing further to do */
3220 if (estate == NULL)
3221 return;
3222
3223 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3224
3225 ExecEndNode(epqstate->recheckplanstate);
3226
3227 foreach(l, estate->es_subplanstates)
3228 {
3230
3232 }
3233
3234 /* throw away the per-estate tuple table, some node may have used it */
3235 ExecResetTupleTable(estate->es_tupleTable, false);
3236
3237 /* Close any result and trigger target relations attached to this EState */
3239
3240 MemoryContextSwitchTo(oldcontext);
3241
3242 /*
3243 * NULLify the partition directory before freeing the executor state.
3244 * Since EvalPlanQualStart() just borrowed the parent EState's directory,
3245 * we'd better leave it up to the parent to delete it.
3246 */
3247 estate->es_partition_directory = NULL;
3248
3249 FreeExecutorState(estate);
3250
3251 /* Mark EPQState idle */
3252 epqstate->origslot = NULL;
3253 epqstate->recheckestate = NULL;
3254 epqstate->recheckplanstate = NULL;
3255 epqstate->relsubs_rowmark = NULL;
3256 epqstate->relsubs_done = NULL;
3257 epqstate->relsubs_blocked = NULL;
3258}
void ExecCloseResultRelations(EState *estate)
Definition execMain.c:1594
void ExecEndNode(PlanState *node)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
void FreeExecutorState(EState *estate)
Definition execUtils.c:197
#define lfirst(lc)
Definition pg_list.h:172
ExecAuxRowMark ** relsubs_rowmark
Definition execnodes.h:1352
TupleTableSlot * origslot
Definition execnodes.h:1340
TupleTableSlot ** relsubs_slot
Definition execnodes.h:1324
List * tuple_table
Definition execnodes.h:1323
PartitionDirectory es_partition_directory
Definition execnodes.h:704

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 2823 of file execMain.c.

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

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 2737 of file execMain.c.

2740{
2741 Index rtsize = parentestate->es_range_table_size;
2742
2743 /* initialize data not changing over EPQState's lifetime */
2744 epqstate->parentestate = parentestate;
2745 epqstate->epqParam = epqParam;
2746 epqstate->resultRelations = resultRelations;
2747
2748 /*
2749 * Allocate space to reference a slot for each potential rti - do so now
2750 * rather than in EvalPlanQualBegin(), as done for other dynamically
2751 * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2752 * that *may* need EPQ later, without forcing the overhead of
2753 * EvalPlanQualBegin().
2754 */
2755 epqstate->tuple_table = NIL;
2757
2758 /* ... and remember data that EvalPlanQualBegin will need */
2759 epqstate->plan = subplan;
2760 epqstate->arowMarks = auxrowmarks;
2761
2762 /* ... and mark the EPQ state inactive */
2763 epqstate->origslot = NULL;
2764 epqstate->recheckestate = NULL;
2765 epqstate->recheckplanstate = NULL;
2766 epqstate->relsubs_rowmark = NULL;
2767 epqstate->relsubs_done = NULL;
2768 epqstate->relsubs_blocked = NULL;
2769}
#define palloc0_array(type, count)
Definition fe_memutils.h:77
List * resultRelations
Definition execnodes.h:1315
List * arowMarks
Definition execnodes.h:1332

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 2934 of file execMain.c.

2935{
2936 MemoryContext oldcontext;
2937 TupleTableSlot *slot;
2938
2939 oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2940 slot = ExecProcNode(epqstate->recheckplanstate);
2941 MemoryContextSwitchTo(oldcontext);
2942
2943 return slot;
2944}
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition executor.h:315

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 2778 of file execMain.c.

2779{
2780 /* If we have a live EPQ query, shut it down */
2781 EvalPlanQualEnd(epqstate);
2782 /* And set/change the plan pointer */
2783 epqstate->plan = subplan;
2784 /* The rowmarks depend on the plan, too */
2785 epqstate->arowMarks = auxrowmarks;
2786}
void EvalPlanQualEnd(EPQState *epqstate)
Definition execMain.c:3198

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2795 of file execMain.c.

2797{
2798 TupleTableSlot **slot;
2799
2800 Assert(relation);
2801 Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2802 slot = &epqstate->relsubs_slot[rti - 1];
2803
2804 if (*slot == NULL)
2805 {
2806 MemoryContext oldcontext;
2807
2808 oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2809 *slot = table_slot_create(relation, &epqstate->tuple_table);
2810 MemoryContextSwitchTo(oldcontext);
2811 }
2812
2813 return *slot;
2814}
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 588 of file execUtils.c.

590{
591 planstate->ps_ProjInfo =
593 planstate->ps_ExprContext,
594 planstate->ps_ResultTupleSlot,
595 planstate,
596 inputDesc);
597}
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition execExpr.c:391
Plan * plan
Definition execnodes.h:1177
TupleTableSlot * ps_ResultTupleSlot
Definition execnodes.h:1215
ProjectionInfo * ps_ProjInfo
Definition execnodes.h:1217
List * targetlist
Definition plannodes.h:233

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 697 of file execUtils.c.

698{
699 TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
700
701 ExecSetSlotDescriptor(slot, tupDesc);
702}
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 2598 of file execMain.c.

2599{
2601 char resname[32];
2602
2603 aerm->rowmark = erm;
2604
2605 /* Look up the resjunk columns associated with this rowmark */
2606 if (erm->markType != ROW_MARK_COPY)
2607 {
2608 /* need ctid for all methods other than COPY */
2609 snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2610 aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2611 resname);
2612 if (!AttributeNumberIsValid(aerm->ctidAttNo))
2613 elog(ERROR, "could not find junk %s column", resname);
2614 }
2615 else
2616 {
2617 /* need wholerow if COPY */
2618 snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2619 aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2620 resname);
2621 if (!AttributeNumberIsValid(aerm->wholeAttNo))
2622 elog(ERROR, "could not find junk %s column", resname);
2623 }
2624
2625 /* if child rel, need tableoid */
2626 if (erm->rti != erm->prti)
2627 {
2628 snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2629 aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2630 resname);
2631 if (!AttributeNumberIsValid(aerm->toidAttNo))
2632 elog(ERROR, "could not find junk %s column", resname);
2633 }
2634
2635 return aerm;
2636}
#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 4494 of file execExpr.c.

4501{
4503 ExprEvalStep scratch = {0};
4504 int maxatt = -1;
4506 ListCell *lc;
4507
4508 /*
4509 * When no columns are actually compared, the result's always true. See
4510 * special case in ExecQual().
4511 */
4512 if (numCols == 0)
4513 return NULL;
4514
4515 state->expr = NULL;
4516 state->flags = EEO_FLAG_IS_QUAL;
4517 state->parent = parent;
4518
4519 scratch.resvalue = &state->resvalue;
4520 scratch.resnull = &state->resnull;
4521
4522 /* compute max needed attribute */
4523 for (int natt = 0; natt < numCols; natt++)
4524 {
4525 int attno = keyColIdx[natt];
4526
4527 if (attno > maxatt)
4528 maxatt = attno;
4529 }
4530 Assert(maxatt >= 0);
4531
4532 /* push deform steps */
4534 scratch.d.fetch.last_var = maxatt;
4535 scratch.d.fetch.fixed = false;
4536 scratch.d.fetch.known_desc = ldesc;
4537 scratch.d.fetch.kind = lops;
4540
4542 scratch.d.fetch.last_var = maxatt;
4543 scratch.d.fetch.fixed = false;
4544 scratch.d.fetch.known_desc = rdesc;
4545 scratch.d.fetch.kind = rops;
4548
4549 /*
4550 * Start comparing at the last field (least significant sort key). That's
4551 * the most likely to be different if we are dealing with sorted input.
4552 */
4553 for (int natt = numCols; --natt >= 0;)
4554 {
4555 int attno = keyColIdx[natt];
4558 Oid foid = eqfunctions[natt];
4559 Oid collid = collations[natt];
4560 FmgrInfo *finfo;
4561 FunctionCallInfo fcinfo;
4563
4564 /* Check permission to call function */
4566 if (aclresult != ACLCHECK_OK)
4568
4570
4571 /* Set up the primary fmgr lookup information */
4572 finfo = palloc0_object(FmgrInfo);
4573 fcinfo = palloc0(SizeForFunctionCallInfo(2));
4574 fmgr_info(foid, finfo);
4575 fmgr_info_set_expr(NULL, finfo);
4576 InitFunctionCallInfoData(*fcinfo, finfo, 2,
4577 collid, NULL, NULL);
4578
4579 /* left arg */
4580 scratch.opcode = EEOP_INNER_VAR;
4581 scratch.d.var.attnum = attno - 1;
4582 scratch.d.var.vartype = latt->atttypid;
4583 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4584 scratch.resvalue = &fcinfo->args[0].value;
4585 scratch.resnull = &fcinfo->args[0].isnull;
4587
4588 /* right arg */
4589 scratch.opcode = EEOP_OUTER_VAR;
4590 scratch.d.var.attnum = attno - 1;
4591 scratch.d.var.vartype = ratt->atttypid;
4592 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4593 scratch.resvalue = &fcinfo->args[1].value;
4594 scratch.resnull = &fcinfo->args[1].isnull;
4596
4597 /* evaluate distinctness */
4598 scratch.opcode = EEOP_NOT_DISTINCT;
4599 scratch.d.func.finfo = finfo;
4600 scratch.d.func.fcinfo_data = fcinfo;
4601 scratch.d.func.fn_addr = finfo->fn_addr;
4602 scratch.d.func.nargs = 2;
4603 scratch.resvalue = &state->resvalue;
4604 scratch.resnull = &state->resnull;
4606
4607 /* then emit EEOP_QUAL to detect if result is false (or null) */
4608 scratch.opcode = EEOP_QUAL;
4609 scratch.d.qualexpr.jumpdone = -1;
4610 scratch.resvalue = &state->resvalue;
4611 scratch.resnull = &state->resnull;
4614 state->steps_len - 1);
4615 }
4616
4617 /* adjust jump targets */
4618 foreach(lc, adjust_jumps)
4619 {
4620 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4621
4622 Assert(as->opcode == EEOP_QUAL);
4623 Assert(as->d.qualexpr.jumpdone == -1);
4624 as->d.qualexpr.jumpdone = state->steps_len;
4625 }
4626
4627 scratch.resvalue = NULL;
4628 scratch.resnull = NULL;
4629 scratch.opcode = EEOP_DONE_RETURN;
4631
4633
4634 return state;
4635}
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3879
Oid collid
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition execExpr.c:2704
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition execExpr.c:3090
static void ExecReadyExpr(ExprState *state)
Definition execExpr.c:935
@ 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:85
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:129
#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:1828
void * palloc0(Size size)
Definition mcxt.c:1417
Oid GetUserId(void)
Definition miscinit.c:470
#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:257
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:178

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

Definition at line 4329 of file execExpr.c.

4333{
4335 ExprEvalStep scratch = {0};
4336 NullableDatum *iresult = NULL;
4338 ListCell *lc;
4339 ListCell *lc2;
4341 intptr_t opcode;
4343
4344 Assert(num_exprs == list_length(collations));
4345
4346 state->parent = parent;
4347
4348 /* Insert setup steps as needed. */
4350
4351 /*
4352 * Make a place to store intermediate hash values between subsequent
4353 * hashing of individual expressions. We only need this if there is more
4354 * than one expression to hash or an initial value plus one expression.
4355 */
4356 if ((int64) num_exprs + (init_value != 0) > 1)
4357 iresult = palloc_object(NullableDatum);
4358
4359 if (init_value == 0)
4360 {
4361 /*
4362 * No initial value, so we can assign the result of the hash function
4363 * for the first hash_expr without having to concern ourselves with
4364 * combining the result with any initial value.
4365 */
4367 opcode = EEOP_HASHDATUM_FIRST;
4368 }
4369 else
4370 {
4371 /*
4372 * Set up operation to set the initial value. Normally we store this
4373 * in the intermediate hash value location, but if there are no exprs
4374 * to hash, store it in the ExprState's result field.
4375 */
4377 scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4378 scratch.resvalue = num_exprs > 0 ? &iresult->value : &state->resvalue;
4379 scratch.resnull = num_exprs > 0 ? &iresult->isnull : &state->resnull;
4380
4382
4383 /*
4384 * When using an initial value use the NEXT32/NEXT32_STRICT ops as the
4385 * FIRST/FIRST_STRICT ops would overwrite the stored initial value.
4386 */
4388 opcode = EEOP_HASHDATUM_NEXT32;
4389 }
4390
4391 forboth(lc, hash_exprs, lc2, collations)
4392 {
4393 Expr *expr = (Expr *) lfirst(lc);
4394 FmgrInfo *finfo;
4395 FunctionCallInfo fcinfo;
4396 int i = foreach_current_index(lc);
4397 Oid funcid;
4398 Oid inputcollid = lfirst_oid(lc2);
4399
4400 funcid = hashfunc_oids[i];
4401
4402 /* Allocate hash function lookup data. */
4403 finfo = palloc0_object(FmgrInfo);
4404 fcinfo = palloc0(SizeForFunctionCallInfo(1));
4405
4406 fmgr_info(funcid, finfo);
4407
4408 /*
4409 * Build the steps to evaluate the hash function's argument, placing
4410 * the value in the 0th argument of the hash func.
4411 */
4412 ExecInitExprRec(expr,
4413 state,
4414 &fcinfo->args[0].value,
4415 &fcinfo->args[0].isnull);
4416
4417 if (i == num_exprs - 1)
4418 {
4419 /* the result for hashing the final expr is stored in the state */
4420 scratch.resvalue = &state->resvalue;
4421 scratch.resnull = &state->resnull;
4422 }
4423 else
4424 {
4425 Assert(iresult != NULL);
4426
4427 /* intermediate values are stored in an intermediate result */
4428 scratch.resvalue = &iresult->value;
4429 scratch.resnull = &iresult->isnull;
4430 }
4431
4432 /*
4433 * NEXT32 opcodes need to look at the intermediate result. We might
4434 * as well just set this for all ops. FIRSTs won't look at it.
4435 */
4436 scratch.d.hashdatum.iresult = iresult;
4437
4438 /* Initialize function call parameter structure too */
4439 InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4440
4441 scratch.d.hashdatum.finfo = finfo;
4442 scratch.d.hashdatum.fcinfo_data = fcinfo;
4443 scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4444
4445 scratch.opcode = opstrict[i] ? strict_opcode : opcode;
4446 scratch.d.hashdatum.jumpdone = -1;
4447
4449 adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1);
4450
4451 /*
4452 * For subsequent keys we must combine the hash value with the
4453 * previous hashes.
4454 */
4456 opcode = EEOP_HASHDATUM_NEXT32;
4457 }
4458
4459 /* adjust jump targets */
4460 foreach(lc, adjust_jumps)
4461 {
4462 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4463
4464 Assert(as->opcode == EEOP_HASHDATUM_FIRST ||
4465 as->opcode == EEOP_HASHDATUM_FIRST_STRICT ||
4466 as->opcode == EEOP_HASHDATUM_NEXT32 ||
4467 as->opcode == EEOP_HASHDATUM_NEXT32_STRICT);
4468 Assert(as->d.hashdatum.jumpdone == -1);
4469 as->d.hashdatum.jumpdone = state->steps_len;
4470 }
4471
4472 scratch.resvalue = NULL;
4473 scratch.resnull = NULL;
4474 scratch.opcode = EEOP_DONE_RETURN;
4476
4478
4479 return state;
4480}
int64_t int64
Definition c.h:615
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition execExpr.c:952
static void ExecCreateExprSetupSteps(ExprState *state, Node *node)
Definition execExpr.c:2909
@ 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:232
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 4168 of file execExpr.c.

4172{
4174 ExprEvalStep scratch = {0};
4175 NullableDatum *iresult = NULL;
4176 intptr_t opcode;
4178
4179 Assert(numCols >= 0);
4180
4181 state->parent = parent;
4182
4183 /*
4184 * Make a place to store intermediate hash values between subsequent
4185 * hashing of individual columns. We only need this if there is more than
4186 * one column to hash or an initial value plus one column.
4187 */
4188 if ((int64) numCols + (init_value != 0) > 1)
4189 iresult = palloc_object(NullableDatum);
4190
4191 /* find the highest attnum so we deform the tuple to that point */
4192 for (int i = 0; i < numCols; i++)
4193 last_attnum = Max(last_attnum, keyColIdx[i]);
4194
4196 scratch.d.fetch.last_var = last_attnum;
4197 scratch.d.fetch.fixed = false;
4198 scratch.d.fetch.kind = ops;
4199 scratch.d.fetch.known_desc = desc;
4202
4203 if (init_value == 0)
4204 {
4205 /*
4206 * No initial value, so we can assign the result of the hash function
4207 * for the first attribute without having to concern ourselves with
4208 * combining the result with any initial value.
4209 */
4210 opcode = EEOP_HASHDATUM_FIRST;
4211 }
4212 else
4213 {
4214 /*
4215 * Set up operation to set the initial value. Normally we store this
4216 * in the intermediate hash value location, but if there are no
4217 * columns to hash, store it in the ExprState's result field.
4218 */
4220 scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4221 scratch.resvalue = numCols > 0 ? &iresult->value : &state->resvalue;
4222 scratch.resnull = numCols > 0 ? &iresult->isnull : &state->resnull;
4223
4225
4226 /*
4227 * When using an initial value use the NEXT32 ops as the FIRST ops
4228 * would overwrite the stored initial value.
4229 */
4230 opcode = EEOP_HASHDATUM_NEXT32;
4231 }
4232
4233 for (int i = 0; i < numCols; i++)
4234 {
4235 FmgrInfo *finfo;
4236 FunctionCallInfo fcinfo;
4237 Oid inputcollid = collations[i];
4238 AttrNumber attnum = keyColIdx[i] - 1;
4239
4240 finfo = &hashfunctions[i];
4241 fcinfo = palloc0(SizeForFunctionCallInfo(1));
4242
4243 /* Initialize function call parameter structure too */
4244 InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4245
4246 /*
4247 * Fetch inner Var for this attnum and store it in the 1st arg of the
4248 * hash func.
4249 */
4250 scratch.opcode = EEOP_INNER_VAR;
4251 scratch.resvalue = &fcinfo->args[0].value;
4252 scratch.resnull = &fcinfo->args[0].isnull;
4253 scratch.d.var.attnum = attnum;
4254 scratch.d.var.vartype = TupleDescAttr(desc, attnum)->atttypid;
4255 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4256
4258
4259 /* Call the hash function */
4260 scratch.opcode = opcode;
4261
4262 if (i == numCols - 1)
4263 {
4264 /*
4265 * The result for hashing the final column is stored in the
4266 * ExprState.
4267 */
4268 scratch.resvalue = &state->resvalue;
4269 scratch.resnull = &state->resnull;
4270 }
4271 else
4272 {
4273 Assert(iresult != NULL);
4274
4275 /* intermediate values are stored in an intermediate result */
4276 scratch.resvalue = &iresult->value;
4277 scratch.resnull = &iresult->isnull;
4278 }
4279
4280 /*
4281 * NEXT32 opcodes need to look at the intermediate result. We might
4282 * as well just set this for all ops. FIRSTs won't look at it.
4283 */
4284 scratch.d.hashdatum.iresult = iresult;
4285
4286 scratch.d.hashdatum.finfo = finfo;
4287 scratch.d.hashdatum.fcinfo_data = fcinfo;
4288 scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4289 scratch.d.hashdatum.jumpdone = -1;
4290
4292
4293 /* subsequent attnums must be combined with the previous */
4294 opcode = EEOP_HASHDATUM_NEXT32;
4295 }
4296
4297 scratch.resvalue = NULL;
4298 scratch.resnull = NULL;
4299 scratch.opcode = EEOP_DONE_RETURN;
4301
4303
4304 return state;
4305}
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 4653 of file execExpr.c.

4660{
4662 ExprEvalStep scratch = {0};
4663 int maxatt = list_length(param_exprs);
4665 ListCell *lc;
4666
4667 state->expr = NULL;
4668 state->flags = EEO_FLAG_IS_QUAL;
4669 state->parent = parent;
4670
4671 scratch.resvalue = &state->resvalue;
4672 scratch.resnull = &state->resnull;
4673
4674 /* push deform steps */
4676 scratch.d.fetch.last_var = maxatt;
4677 scratch.d.fetch.fixed = false;
4678 scratch.d.fetch.known_desc = desc;
4679 scratch.d.fetch.kind = lops;
4682
4684 scratch.d.fetch.last_var = maxatt;
4685 scratch.d.fetch.fixed = false;
4686 scratch.d.fetch.known_desc = desc;
4687 scratch.d.fetch.kind = rops;
4690
4691 for (int attno = 0; attno < maxatt; attno++)
4692 {
4693 Form_pg_attribute att = TupleDescAttr(desc, attno);
4694 Oid foid = eqfunctions[attno];
4695 Oid collid = collations[attno];
4696 FmgrInfo *finfo;
4697 FunctionCallInfo fcinfo;
4699
4700 /* Check permission to call function */
4702 if (aclresult != ACLCHECK_OK)
4704
4706
4707 /* Set up the primary fmgr lookup information */
4708 finfo = palloc0_object(FmgrInfo);
4709 fcinfo = palloc0(SizeForFunctionCallInfo(2));
4710 fmgr_info(foid, finfo);
4711 fmgr_info_set_expr(NULL, finfo);
4712 InitFunctionCallInfoData(*fcinfo, finfo, 2,
4713 collid, NULL, NULL);
4714
4715 /* left arg */
4716 scratch.opcode = EEOP_INNER_VAR;
4717 scratch.d.var.attnum = attno;
4718 scratch.d.var.vartype = att->atttypid;
4719 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4720 scratch.resvalue = &fcinfo->args[0].value;
4721 scratch.resnull = &fcinfo->args[0].isnull;
4723
4724 /* right arg */
4725 scratch.opcode = EEOP_OUTER_VAR;
4726 scratch.d.var.attnum = attno;
4727 scratch.d.var.vartype = att->atttypid;
4728 scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT;
4729 scratch.resvalue = &fcinfo->args[1].value;
4730 scratch.resnull = &fcinfo->args[1].isnull;
4732
4733 /* evaluate distinctness */
4734 scratch.opcode = EEOP_NOT_DISTINCT;
4735 scratch.d.func.finfo = finfo;
4736 scratch.d.func.fcinfo_data = fcinfo;
4737 scratch.d.func.fn_addr = finfo->fn_addr;
4738 scratch.d.func.nargs = 2;
4739 scratch.resvalue = &state->resvalue;
4740 scratch.resnull = &state->resnull;
4742
4743 /* then emit EEOP_QUAL to detect if result is false (or null) */
4744 scratch.opcode = EEOP_QUAL;
4745 scratch.d.qualexpr.jumpdone = -1;
4746 scratch.resvalue = &state->resvalue;
4747 scratch.resnull = &state->resnull;
4750 state->steps_len - 1);
4751 }
4752
4753 /* adjust jump targets */
4754 foreach(lc, adjust_jumps)
4755 {
4756 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4757
4758 Assert(as->opcode == EEOP_QUAL);
4759 Assert(as->d.qualexpr.jumpdone == -1);
4760 as->d.qualexpr.jumpdone = state->steps_len;
4761 }
4762
4763 scratch.resvalue = NULL;
4764 scratch.resnull = NULL;
4765 scratch.opcode = EEOP_DONE_RETURN;
4767
4769
4770 return state;
4771}

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

396{
399 ExprEvalStep scratch = {0};
400 ListCell *lc;
401
402 projInfo->pi_exprContext = econtext;
403 /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
404 projInfo->pi_state.type = T_ExprState;
405 state = &projInfo->pi_state;
406 state->expr = (Expr *) targetList;
407 state->parent = parent;
408 state->ext_params = NULL;
409
410 state->resultslot = slot;
411
412 /* Insert setup steps as needed */
413 ExecCreateExprSetupSteps(state, (Node *) targetList);
414
415 /* Now compile each tlist column */
416 foreach(lc, targetList)
417 {
419 Var *variable = NULL;
420 AttrNumber attnum = 0;
421 bool isSafeVar = false;
422
423 /*
424 * If tlist expression is a safe non-system Var, use the fast-path
425 * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
426 * CheckVarSlotCompatibility() during plan startup. If a source slot
427 * was provided, we make the equivalent tests here; if a slot was not
428 * provided, we assume that no check is needed because we're dealing
429 * with a non-relation-scan-level expression.
430 */
431 if (tle->expr != NULL &&
432 IsA(tle->expr, Var) &&
433 ((Var *) tle->expr)->varattno > 0)
434 {
435 /* Non-system Var, but how safe is it? */
436 variable = (Var *) tle->expr;
437 attnum = variable->varattno;
438
439 if (inputDesc == NULL)
440 isSafeVar = true; /* can't check, just assume OK */
441 else if (attnum <= inputDesc->natts)
442 {
444
445 /*
446 * If user attribute is dropped or has a type mismatch, don't
447 * use ASSIGN_*_VAR. Instead let the normal expression
448 * machinery handle it (which'll possibly error out).
449 */
450 if (!attr->attisdropped && variable->vartype == attr->atttypid)
451 {
452 isSafeVar = true;
453 }
454 }
455 }
456
457 if (isSafeVar)
458 {
459 /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
460 switch (variable->varno)
461 {
462 case INNER_VAR:
463 /* get the tuple from the inner node */
465 break;
466
467 case OUTER_VAR:
468 /* get the tuple from the outer node */
470 break;
471
472 /* INDEX_VAR is handled by default case */
473
474 default:
475
476 /*
477 * Get the tuple from the relation being scanned, or the
478 * old/new tuple slot, if old/new values were requested.
479 */
480 switch (variable->varreturningtype)
481 {
484 break;
487 state->flags |= EEO_FLAG_HAS_OLD;
488 break;
491 state->flags |= EEO_FLAG_HAS_NEW;
492 break;
493 }
494 break;
495 }
496
497 scratch.d.assign_var.attnum = attnum - 1;
498 scratch.d.assign_var.resultnum = tle->resno - 1;
500 }
501 else
502 {
503 /*
504 * Otherwise, compile the column expression normally.
505 *
506 * We can't tell the expression to evaluate directly into the
507 * result slot, as the result slot (and the exprstate for that
508 * matter) can change between executions. We instead evaluate
509 * into the ExprState's resvalue/resnull and then move.
510 */
512 &state->resvalue, &state->resnull);
513
514 /*
515 * Column might be referenced multiple times in upper nodes, so
516 * force value to R/O - but only if it could be an expanded datum.
517 */
518 if (get_typlen(exprType((Node *) tle->expr)) == -1)
520 else
521 scratch.opcode = EEOP_ASSIGN_TMP;
522 scratch.d.assign_tmp.resultnum = tle->resno - 1;
524 }
525 }
526
529
531
532 return projInfo;
533}
@ 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:87
#define EEO_FLAG_HAS_NEW
Definition execnodes.h:89
int16 get_typlen(Oid typid)
Definition lsyscache.c:2417
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:258
@ VAR_RETURNING_NEW
Definition primnodes.h:259
#define OUTER_VAR
Definition primnodes.h:244
#define INNER_VAR
Definition primnodes.h:243
NodeTag type
Definition execnodes.h:280

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 2410 of file execMain.c.

2415{
2418 bool write_comma = false;
2419 bool write_comma_collist = false;
2420 int i;
2422 bool table_perm = false;
2423 bool any_perm = false;
2424
2425 /*
2426 * Check if RLS is enabled and should be active for the relation; if so,
2427 * then don't return anything. Otherwise, go through normal permission
2428 * checks.
2429 */
2430 if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2431 return NULL;
2432
2434
2436
2437 /*
2438 * Check if the user has permissions to see the row. Table-level SELECT
2439 * allows access to all columns. If the user does not have table-level
2440 * SELECT then we check each column and include those the user has SELECT
2441 * rights on. Additionally, we always include columns the user provided
2442 * data for.
2443 */
2445 if (aclresult != ACLCHECK_OK)
2446 {
2447 /* Set up the buffer for the column list */
2450 }
2451 else
2452 table_perm = any_perm = true;
2453
2454 /* Make sure the tuple is fully deconstructed */
2455 slot_getallattrs(slot);
2456
2457 for (i = 0; i < tupdesc->natts; i++)
2458 {
2459 bool column_perm = false;
2460 char *val;
2461 int vallen;
2463
2464 /* ignore dropped columns */
2465 if (att->attisdropped)
2466 continue;
2467
2468 if (!table_perm)
2469 {
2470 /*
2471 * No table-level SELECT, so need to make sure they either have
2472 * SELECT rights on the column or that they have provided the data
2473 * for the column. If not, omit this column from the error
2474 * message.
2475 */
2476 aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2480 {
2481 column_perm = any_perm = true;
2482
2485 else
2486 write_comma_collist = true;
2487
2489 }
2490 }
2491
2492 if (table_perm || column_perm)
2493 {
2494 if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
2495 val = "virtual";
2496 else if (slot->tts_isnull[i])
2497 val = "null";
2498 else
2499 {
2500 Oid foutoid;
2501 bool typisvarlena;
2502
2503 getTypeOutputInfo(att->atttypid,
2504 &foutoid, &typisvarlena);
2506 }
2507
2508 if (write_comma)
2510 else
2511 write_comma = true;
2512
2513 /* truncate if needed */
2514 vallen = strlen(val);
2515 if (vallen <= maxfieldlen)
2516 appendBinaryStringInfo(&buf, val, vallen);
2517 else
2518 {
2519 vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2520 appendBinaryStringInfo(&buf, val, vallen);
2521 appendStringInfoString(&buf, "...");
2522 }
2523 }
2524 }
2525
2526 /* If we end up with zero columns being returned, then return NULL. */
2527 if (!any_perm)
2528 return NULL;
2529
2531
2532 if (!table_perm)
2533 {
2536
2537 return collist.data;
2538 }
2539
2540 return buf.data;
2541}
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition aclchk.c:3911
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4082
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
#define NameStr(name)
Definition c.h:837
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition fmgr.c:1764
long val
Definition informix.c:689
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3129
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition mbutils.c:1211
#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:390

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

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

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

906{
907 Datum ret;
908 bool isnull;
909
910 /* short-circuit (here and in ExecInitCheck) for empty restriction list */
911 if (state == NULL)
912 return true;
913
914 /* verify that expression was not compiled using ExecInitQual */
915 Assert(!(state->flags & EEO_FLAG_IS_QUAL));
916
917 ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
918
919 if (isnull)
920 return true;
921
922 return DatumGetBool(ret);
923}
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:439
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 542 of file execIndexing.c.

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

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 648 of file execMain.c.

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

586{
587 ListCell *l;
588 bool result = true;
589
590#ifdef USE_ASSERT_CHECKING
592
593 /* Check that rteperminfos is consistent with rangeTable */
594 foreach(l, rangeTable)
595 {
597
598 if (rte->perminfoindex != 0)
599 {
600 /* Sanity checks */
601
602 /*
603 * Only relation RTEs and subquery RTEs that were once relation
604 * RTEs (views, property graphs) have their perminfoindex set.
605 */
606 Assert(rte->rtekind == RTE_RELATION ||
607 (rte->rtekind == RTE_SUBQUERY &&
608 (rte->relkind == RELKIND_VIEW || rte->relkind == RELKIND_PROPGRAPH)));
609
610 (void) getRTEPermissionInfo(rteperminfos, rte);
611 /* Many-to-one mapping not allowed */
612 Assert(!bms_is_member(rte->perminfoindex, indexset));
613 indexset = bms_add_member(indexset, rte->perminfoindex);
614 }
615 }
616
617 /* All rteperminfos are referenced */
618 Assert(bms_num_members(indexset) == list_length(rteperminfos));
619#endif
620
621 foreach(l, rteperminfos)
622 {
624
625 Assert(OidIsValid(perminfo->relid));
627 if (!result)
628 {
629 if (ereport_on_violation)
632 get_rel_name(perminfo->relid));
633 return false;
634 }
635 }
636
638 result = (*ExecutorCheckPerms_hook) (rangeTable, rteperminfos,
639 ereport_on_violation);
640 return result;
641}
@ ACLCHECK_NO_PRIV
Definition acl.h:185
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:744
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition execMain.c:76
bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
Definition execMain.c:648
char * get_rel_name(Oid relid)
Definition lsyscache.c:2148
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2223
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 1190 of file execUtils.c.

1191{
1192 int len = 0;
1193 ListCell *tl;
1194
1195 foreach(tl, targetlist)
1196 {
1198
1199 if (!curTle->resjunk)
1200 len++;
1201 }
1202 return len;
1203}

References fb(), len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)
extern

Definition at line 2210 of file execTuples.c.

2211{
2212 return ExecTypeFromTLInternal(targetList, true);
2213}
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 1654 of file execMain.c.

1655{
1656 int i;
1657
1658 for (i = 0; i < estate->es_range_table_size; i++)
1659 {
1660 if (estate->es_relations[i])
1661 table_close(estate->es_relations[i], NoLock);
1662 }
1663}
#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 1594 of file execMain.c.

1595{
1596 ListCell *l;
1597
1598 /*
1599 * close indexes of result relation(s) if any. (Rels themselves are
1600 * closed in ExecCloseRangeTableRelations())
1601 *
1602 * In addition, close the stub RTs that may be in each resultrel's
1603 * ri_ancestorResultRels.
1604 */
1605 foreach(l, estate->es_opened_result_relations)
1606 {
1607 ResultRelInfo *resultRelInfo = lfirst(l);
1608 ListCell *lc;
1609
1610 ExecCloseIndices(resultRelInfo);
1611 foreach(lc, resultRelInfo->ri_ancestorResultRels)
1612 {
1614
1615 /*
1616 * Ancestors with RTI > 0 (should only be the root ancestor) are
1617 * closed by ExecCloseRangeTableRelations.
1618 */
1619 if (rInfo->ri_RangeTableIndex > 0)
1620 continue;
1621
1622 table_close(rInfo->ri_RelationDesc, NoLock);
1623 }
1624 }
1625
1626 /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
1627 foreach(l, estate->es_trig_target_relations)
1628 {
1629 ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1630
1631 /*
1632 * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
1633 * might be issuing a duplicate close against a Relation opened by
1634 * ExecGetRangeTableRelation.
1635 */
1636 Assert(resultRelInfo->ri_RangeTableIndex == 0);
1637
1638 /*
1639 * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
1640 * these rels, we needn't call ExecCloseIndices either.
1641 */
1642 Assert(resultRelInfo->ri_NumIndices == 0);
1643
1644 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1645 }
1646}
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Index ri_RangeTableIndex
Definition execnodes.h:489
List * ri_ancestorResultRels
Definition execnodes.h:640

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 608 of file execUtils.c.

610{
611 if (tlist_matches_tupdesc(planstate,
612 planstate->plan->targetlist,
613 varno,
614 inputDesc))
615 {
616 planstate->ps_ProjInfo = NULL;
617 planstate->resultopsset = planstate->scanopsset;
618 planstate->resultopsfixed = planstate->scanopsfixed;
619 planstate->resultops = planstate->scanops;
620 }
621 else
622 {
623 if (!planstate->ps_ResultTupleSlot)
624 {
626 planstate->resultops = &TTSOpsVirtual;
627 planstate->resultopsfixed = true;
628 planstate->resultopsset = true;
629 }
631 }
632}
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:635
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition execUtils.c:588
const TupleTableSlotOps * resultops
Definition execnodes.h:1254
bool resultopsset
Definition execnodes.h:1262
const TupleTableSlotOps * scanops
Definition execnodes.h:1251
bool scanopsset
Definition execnodes.h:1259
bool scanopsfixed
Definition execnodes.h:1255
bool resultopsfixed
Definition execnodes.h:1258

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 1999 of file execMain.c.

2001{
2002 Relation rel = resultRelInfo->ri_RelationDesc;
2003 TupleDesc tupdesc = RelationGetDescr(rel);
2004 TupleConstr *constr = tupdesc->constr;
2007
2008 Assert(constr); /* we should not be called otherwise */
2009
2010 /*
2011 * Verify not-null constraints.
2012 *
2013 * Not-null constraints on virtual generated columns are collected and
2014 * checked separately below.
2015 */
2016 if (constr->has_not_null)
2017 {
2018 for (AttrNumber attnum = 1; attnum <= tupdesc->natts; attnum++)
2019 {
2020 Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
2021
2022 if (att->attnotnull && att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
2024 else if (att->attnotnull && slot_attisnull(slot, attnum))
2025 ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
2026 }
2027 }
2028
2029 /*
2030 * Verify not-null constraints on virtual generated column, if any.
2031 */
2033 {
2035
2036 attnum = ExecRelGenVirtualNotNull(resultRelInfo, slot, estate,
2039 ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
2040 }
2041
2042 /*
2043 * Verify check constraints.
2044 */
2045 if (rel->rd_rel->relchecks > 0)
2046 {
2047 const char *failed;
2048
2049 if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2050 {
2051 char *val_desc;
2052 Relation orig_rel = rel;
2053
2054 /*
2055 * If the tuple has been routed, it's been converted to the
2056 * partition's rowtype, which might differ from the root table's.
2057 * We must convert it back to the root table's rowtype so that
2058 * val_desc shown error message matches the input tuple.
2059 */
2060 if (resultRelInfo->ri_RootResultRelInfo)
2061 {
2062 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2064 AttrMap *map;
2065
2066 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2067 /* a reverse map */
2069 tupdesc,
2070 false);
2071
2072 /*
2073 * Partition-specific slot's tupdesc can't be changed, so
2074 * allocate a new one.
2075 */
2076 if (map != NULL)
2077 slot = execute_attr_map_slot(map, slot,
2078 MakeTupleTableSlot(tupdesc, &TTSOpsVirtual, 0));
2080 ExecGetUpdatedCols(rootrel, estate));
2081 rel = rootrel->ri_RelationDesc;
2082 }
2083 else
2084 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2085 ExecGetUpdatedCols(resultRelInfo, estate));
2087 slot,
2088 tupdesc,
2090 64);
2091 ereport(ERROR,
2093 errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2095 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2096 errtableconstraint(orig_rel, failed)));
2097 }
2098 }
2099}
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:2178
char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition execMain.c:2410
AttrNumber ExecRelGenVirtualNotNull(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, List *notnull_virtual_attrs)
Definition execMain.c:2113
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition execMain.c:1797
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops, uint16 flags)
Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1366
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1387
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
struct ResultRelInfo * ri_RootResultRelInfo
Definition execnodes.h:630
bool has_not_null
Definition tupdesc.h:45
TupleConstr * constr
Definition tupdesc.h:159
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:403

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 709 of file execUtils.c.

712{
714 TupleDesc tupDesc;
715
717 tupDesc = ExecGetResultType(outerPlan);
718
719 ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops, 0);
720}
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops, uint16 flags)
TupleDesc ExecGetResultType(PlanState *planstate)
Definition execUtils.c:500
#define outerPlanState(node)
Definition execnodes.h:1273
#define outerPlan(node)
Definition plannodes.h:265

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:132
char * cursor_name
Definition primnodes.h:2125
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:438

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 563 of file execProcnode.c.

564{
565 /*
566 * do nothing when we get to the end of a leaf on tree.
567 */
568 if (node == NULL)
569 return;
570
571 /*
572 * Make sure there's enough stack available. Need to check here, in
573 * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
574 * guaranteed that ExecProcNode() is reached for all nodes.
575 */
577
578 if (node->chgParam != NULL)
579 {
580 bms_free(node->chgParam);
581 node->chgParam = NULL;
582 }
583
584 switch (nodeTag(node))
585 {
586 /*
587 * control nodes
588 */
589 case T_ResultState:
590 ExecEndResult((ResultState *) node);
591 break;
592
595 break;
596
599 break;
600
601 case T_AppendState:
602 ExecEndAppend((AppendState *) node);
603 break;
604
607 break;
608
611 break;
612
613 case T_BitmapAndState:
615 break;
616
617 case T_BitmapOrState:
619 break;
620
621 /*
622 * scan nodes
623 */
624 case T_SeqScanState:
626 break;
627
630 break;
631
632 case T_GatherState:
633 ExecEndGather((GatherState *) node);
634 break;
635
638 break;
639
640 case T_IndexScanState:
642 break;
643
646 break;
647
650 break;
651
654 break;
655
656 case T_TidScanState:
658 break;
659
662 break;
663
666 break;
667
670 break;
671
674 break;
675
676 case T_CteScanState:
678 break;
679
682 break;
683
686 break;
687
688 /*
689 * join nodes
690 */
691 case T_NestLoopState:
693 break;
694
695 case T_MergeJoinState:
697 break;
698
699 case T_HashJoinState:
701 break;
702
703 /*
704 * materialization nodes
705 */
706 case T_MaterialState:
708 break;
709
710 case T_SortState:
711 ExecEndSort((SortState *) node);
712 break;
713
716 break;
717
718 case T_MemoizeState:
720 break;
721
722 case T_GroupState:
723 ExecEndGroup((GroupState *) node);
724 break;
725
726 case T_AggState:
727 ExecEndAgg((AggState *) node);
728 break;
729
730 case T_WindowAggState:
732 break;
733
734 case T_UniqueState:
735 ExecEndUnique((UniqueState *) node);
736 break;
737
738 case T_HashState:
739 ExecEndHash((HashState *) node);
740 break;
741
742 case T_SetOpState:
743 ExecEndSetOp((SetOpState *) node);
744 break;
745
746 case T_LockRowsState:
748 break;
749
750 case T_LimitState:
751 ExecEndLimit((LimitState *) node);
752 break;
753
754 /* No clean up actions for these nodes. */
758 break;
759
760 default:
761 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
762 break;
763 }
764}
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
void ExecEndAgg(AggState *node)
Definition nodeAgg.c:4396
void ExecEndAppend(AppendState *node)
Definition nodeAppend.c:403
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:252
void ExecEndGroup(GroupState *node)
Definition nodeGroup.c:227
void ExecEndHash(HashState *node)
Definition nodeHash.c:452
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:692
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:1209

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

423{
425
426 retDatum = state->evalfunc(state, econtext, NULL);
427
428 Assert(retDatum == (Datum) 0);
429}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:243

References Assert, fb(), and PG_USED_FOR_ASSERTS_ONLY.

Referenced by ExecEvalExprNoReturnSwitchContext().

◆ ExecEvalExprNoReturnSwitchContext()

static void ExecEvalExprNoReturnSwitchContext ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 461 of file executor.h.

463{
465
467 ExecEvalExprNoReturn(state, econtext);
469}
static void ExecEvalExprNoReturn(ExprState *state, ExprContext *econtext)
Definition executor.h:421

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 2575 of file execMain.c.

2576{
2577 if (rti > 0 && rti <= estate->es_range_table_size &&
2578 estate->es_rowmarks != NULL)
2579 {
2580 ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2581
2582 if (erm)
2583 return erm;
2584 }
2585 if (!missing_ok)
2586 elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2587 return NULL;
2588}

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecGetAllNullSlot()

TupleTableSlot * ExecGetAllNullSlot ( EState estate,
ResultRelInfo relInfo 
)
extern

Definition at line 1278 of file execUtils.c.

1279{
1280 if (relInfo->ri_AllNullSlot == NULL)
1281 {
1282 Relation rel = relInfo->ri_RelationDesc;
1283 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1284 TupleTableSlot *slot;
1285
1286 slot = ExecInitExtraTupleSlot(estate,
1287 RelationGetDescr(rel),
1290
1291 relInfo->ri_AllNullSlot = slot;
1292
1293 MemoryContextSwitchTo(oldcontext);
1294 }
1295
1296 return relInfo->ri_AllNullSlot;
1297}
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 1423 of file execUtils.c.

1424{
1425 Bitmapset *ret;
1427
1429
1430 ret = bms_union(ExecGetUpdatedCols(relinfo, estate),
1432
1434
1435 return ret;
1436}
Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1408
#define GetPerTupleMemoryContext(estate)
Definition executor.h:665

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 1449 of file execMain.c.

1450{
1452 Relation partRel = resultRelInfo->ri_RelationDesc;
1454
1455 if (!partRel->rd_rel->relispartition)
1456 elog(ERROR, "cannot find ancestors of a non-partition result relation");
1458 rootRelOid = RelationGetRelid(rootRelInfo->ri_RelationDesc);
1459 if (resultRelInfo->ri_ancestorResultRels == NIL)
1460 {
1461 ListCell *lc;
1464
1465 foreach(lc, oids)
1466 {
1470
1471 /*
1472 * Ignore the root ancestor here, and use ri_RootResultRelInfo
1473 * (below) for it instead. Also, we stop climbing up the
1474 * hierarchy when we find the table that was mentioned in the
1475 * query.
1476 */
1477 if (ancOid == rootRelOid)
1478 break;
1479
1480 /*
1481 * All ancestors up to the root target relation must have been
1482 * locked by the planner or AcquireExecutorLocks().
1483 */
1486
1487 /* dummy rangetable index */
1489 estate->es_instrument);
1491 }
1493 resultRelInfo->ri_ancestorResultRels = ancResultRels;
1494 }
1495
1496 /* We must have found some ancestor */
1497 Assert(resultRelInfo->ri_ancestorResultRels != NIL);
1498
1499 return resultRelInfo->ri_ancestorResultRels;
1500}
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
Definition execMain.c:1262
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 1305 of file execUtils.c.

1306{
1307 /* If we didn't already do so, compute the map for this child. */
1308 if (!resultRelInfo->ri_ChildToRootMapValid)
1309 {
1311
1312 if (rootRelInfo)
1313 resultRelInfo->ri_ChildToRootMap =
1315 RelationGetDescr(rootRelInfo->ri_RelationDesc));
1316 else /* this isn't a child result rel */
1317 resultRelInfo->ri_ChildToRootMap = NULL;
1318
1319 resultRelInfo->ri_ChildToRootMapValid = true;
1320 }
1321
1322 return resultRelInfo->ri_ChildToRootMap;
1323}
TupleConversionMap * ri_ChildToRootMap
Definition execnodes.h:612
bool ri_ChildToRootMapValid
Definition execnodes.h:613
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 568 of file execUtils.c.

569{
571
575}
const TupleTableSlotOps * ExecGetCommonSlotOps(PlanState **planstates, int nplans)
Definition execUtils.c:541
#define innerPlanState(node)
Definition execnodes.h:1272
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 541 of file execUtils.c.

542{
543 const TupleTableSlotOps *result;
544 bool isfixed;
545
546 if (nplans <= 0)
547 return NULL;
548 result = ExecGetResultSlotOps(planstates[0], &isfixed);
549 if (!isfixed)
550 return NULL;
551 for (int i = 1; i < nplans; i++)
552 {
554
556 if (!isfixed)
557 return NULL;
558 if (result != thisops)
559 return NULL;
560 }
561 return result;
562}
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition execUtils.c:509

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

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

◆ ExecGetExtraUpdatedCols()

Bitmapset * ExecGetExtraUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)
extern

Definition at line 1408 of file execUtils.c.

1409{
1410 /* Compute the info if we didn't already */
1411 if (!relinfo->ri_extraUpdatedCols_valid)
1413 return relinfo->ri_extraUpdatedCols;
1414}
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 1366 of file execUtils.c.

1367{
1369
1370 if (perminfo == NULL)
1371 return NULL;
1372
1373 /* Map the columns to child's attribute numbers if needed. */
1374 if (relinfo->ri_RootResultRelInfo)
1375 {
1377
1378 if (map)
1379 return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
1380 }
1381
1382 return perminfo->insertedCols;
1383}
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition execUtils.c:1331
static RTEPermissionInfo * GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1443
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 226 of file executor.h.

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

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 830 of file execUtils.c.

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

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 1494 of file execUtils.c.

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

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 509 of file execUtils.c.

510{
511 if (planstate->resultopsset && planstate->resultops)
512 {
513 if (isfixed)
514 *isfixed = planstate->resultopsfixed;
515 return planstate->resultops;
516 }
517
518 if (isfixed)
519 {
520 if (planstate->resultopsset)
521 *isfixed = planstate->resultopsfixed;
522 else if (planstate->ps_ResultTupleSlot)
523 *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
524 else
525 *isfixed = false;
526 }
527
528 if (!planstate->ps_ResultTupleSlot)
529 return &TTSOpsVirtual;
530
531 return planstate->ps_ResultTupleSlot->tts_ops;
532}
const TupleTableSlotOps *const tts_ops
Definition tuptable.h:127
#define TTS_FIXED(slot)
Definition tuptable.h:108

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

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

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot * ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)
extern

Definition at line 1253 of file execUtils.c.

1254{
1255 if (relInfo->ri_ReturningSlot == NULL)
1256 {
1257 Relation rel = relInfo->ri_RelationDesc;
1258 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1259
1260 relInfo->ri_ReturningSlot =
1262 RelationGetDescr(rel),
1264
1265 MemoryContextSwitchTo(oldcontext);
1266 }
1267
1268 return relInfo->ri_ReturningSlot;
1269}

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 1331 of file execUtils.c.

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

1232{
1233 if (relInfo->ri_TrigNewSlot == NULL)
1234 {
1235 Relation rel = relInfo->ri_RelationDesc;
1236 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1237
1238 relInfo->ri_TrigNewSlot =
1240 RelationGetDescr(rel),
1242
1243 MemoryContextSwitchTo(oldcontext);
1244 }
1245
1246 return relInfo->ri_TrigNewSlot;
1247}

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 1209 of file execUtils.c.

1210{
1211 if (relInfo->ri_TrigOldSlot == NULL)
1212 {
1213 Relation rel = relInfo->ri_RelationDesc;
1214 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1215
1216 relInfo->ri_TrigOldSlot =
1218 RelationGetDescr(rel),
1220
1221 MemoryContextSwitchTo(oldcontext);
1222 }
1223
1224 return relInfo->ri_TrigOldSlot;
1225}

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 1362 of file execMain.c.

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

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 1387 of file execUtils.c.

1388{
1390
1391 if (perminfo == NULL)
1392 return NULL;
1393
1394 /* Map the columns to child's attribute numbers if needed. */
1395 if (relinfo->ri_RootResultRelInfo)
1396 {
1398
1399 if (map)
1400 return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
1401 }
1402
1403 return perminfo->updatedCols;
1404}

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 824 of file nodeModifyTable.c.

827{
828 ProjectionInfo *newProj = relinfo->ri_projectNew;
829 ExprContext *econtext;
830
831 /* Use a few extra Asserts to protect against outside callers */
832 Assert(relinfo->ri_projectNewInfoValid);
833 Assert(planSlot != NULL && !TTS_EMPTY(planSlot));
835
836 econtext = newProj->pi_exprContext;
837 econtext->ecxt_outertuple = planSlot;
838 econtext->ecxt_scantuple = oldSlot;
839 return ExecProject(newProj);
840}
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition executor.h:486
#define TTS_EMPTY(slot)
Definition tuptable.h:92

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

337{
338 /* short-circuit (here and in ExecCheck) for empty restriction list */
339 if (qual == NIL)
340 return NULL;
341
342 Assert(IsA(qual, List));
343
344 /*
345 * Just convert the implicit-AND list to an explicit AND (if there's more
346 * than one entry), and compile normally. Unlike ExecQual, we can't
347 * short-circuit on NULL results, so the regular AND behavior is needed.
348 */
349 return ExecInitExpr(make_ands_explicit(qual), parent);
350}
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()

◆ ExecInitExprList()

List * ExecInitExprList ( List nodes,
PlanState parent 
)
extern

Definition at line 356 of file execExpr.c.

357{
358 List *result = NIL;
359 ListCell *lc;
360
361 foreach(lc, nodes)
362 {
363 Expr *e = lfirst(lc);
364
365 result = lappend(result, ExecInitExpr(e, parent));
366 }
367
368 return result;
369}
e

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

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

◆ ExecInitExprWithContext()

ExprState * ExecInitExprWithContext ( Expr node,
PlanState parent,
Node escontext 
)
extern

Definition at line 163 of file execExpr.c.

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

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

Referenced by ExecInitExpr(), and ExecPrepareExprWithContext().

◆ ExecInitExprWithParams()

ExprState * ExecInitExprWithParams ( Expr node,
ParamListInfo  ext_params 
)
extern

Definition at line 201 of file execExpr.c.

202{
204 ExprEvalStep scratch = {0};
205
206 /* Special case: NULL expression produces a NULL ExprState pointer */
207 if (node == NULL)
208 return NULL;
209
210 /* Initialize ExprState with empty step list */
212 state->expr = node;
213 state->parent = NULL;
214 state->ext_params = ext_params;
215
216 /* Insert setup steps as needed */
218
219 /* Compile the expression proper */
220 ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
221
222 /* Finally, append a DONE step */
223 scratch.opcode = EEOP_DONE_RETURN;
225
227
228 return state;
229}

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 446 of file execSRF.c.

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

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 143 of file execProcnode.c.

144{
145 PlanState *result;
146 List *subps;
147 ListCell *l;
148
149 /*
150 * do nothing when we get to the end of a leaf on tree.
151 */
152 if (node == NULL)
153 return NULL;
154
155 /*
156 * Make sure there's enough stack available. Need to check here, in
157 * addition to ExecProcNode() (via ExecProcNodeFirst()), to ensure the
158 * stack isn't overrun while initializing the node tree.
159 */
161
162 switch (nodeTag(node))
163 {
164 /*
165 * control nodes
166 */
167 case T_Result:
168 result = (PlanState *) ExecInitResult((Result *) node,
169 estate, eflags);
170 break;
171
172 case T_ProjectSet:
173 result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
174 estate, eflags);
175 break;
176
177 case T_ModifyTable:
178 result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
179 estate, eflags);
180 break;
181
182 case T_Append:
183 result = (PlanState *) ExecInitAppend((Append *) node,
184 estate, eflags);
185 break;
186
187 case T_MergeAppend:
188 result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
189 estate, eflags);
190 break;
191
192 case T_RecursiveUnion:
193 result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
194 estate, eflags);
195 break;
196
197 case T_BitmapAnd:
198 result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
199 estate, eflags);
200 break;
201
202 case T_BitmapOr:
203 result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
204 estate, eflags);
205 break;
206
207 /*
208 * scan nodes
209 */
210 case T_SeqScan:
211 result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
212 estate, eflags);
213 break;
214
215 case T_SampleScan:
216 result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
217 estate, eflags);
218 break;
219
220 case T_IndexScan:
221 result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
222 estate, eflags);
223 break;
224
225 case T_IndexOnlyScan:
226 result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
227 estate, eflags);
228 break;
229
232 estate, eflags);
233 break;
234
235 case T_BitmapHeapScan:
236 result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
237 estate, eflags);
238 break;
239
240 case T_TidScan:
241 result = (PlanState *) ExecInitTidScan((TidScan *) node,
242 estate, eflags);
243 break;
244
245 case T_TidRangeScan:
246 result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
247 estate, eflags);
248 break;
249
250 case T_SubqueryScan:
251 result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
252 estate, eflags);
253 break;
254
255 case T_FunctionScan:
256 result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
257 estate, eflags);
258 break;
259
260 case T_TableFuncScan:
261 result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
262 estate, eflags);
263 break;
264
265 case T_ValuesScan:
266 result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
267 estate, eflags);
268 break;
269
270 case T_CteScan:
271 result = (PlanState *) ExecInitCteScan((CteScan *) node,
272 estate, eflags);
273 break;
274
277 estate, eflags);
278 break;
279
280 case T_WorkTableScan:
281 result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
282 estate, eflags);
283 break;
284
285 case T_ForeignScan:
286 result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
287 estate, eflags);
288 break;
289
290 case T_CustomScan:
291 result = (PlanState *) ExecInitCustomScan((CustomScan *) node,
292 estate, eflags);
293 break;
294
295 /*
296 * join nodes
297 */
298 case T_NestLoop:
299 result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
300 estate, eflags);
301 break;
302
303 case T_MergeJoin:
304 result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
305 estate, eflags);
306 break;
307
308 case T_HashJoin:
309 result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
310 estate, eflags);
311 break;
312
313 /*
314 * materialization nodes
315 */
316 case T_Material:
317 result = (PlanState *) ExecInitMaterial((Material *) node,
318 estate, eflags);
319 break;
320
321 case T_Sort:
322 result = (PlanState *) ExecInitSort((Sort *) node,
323 estate, eflags);
324 break;
325
328 estate, eflags);
329 break;
330
331 case T_Memoize:
332 result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
333 eflags);
334 break;
335
336 case T_Group:
337 result = (PlanState *) ExecInitGroup((Group *) node,
338 estate, eflags);
339 break;
340
341 case T_Agg:
342 result = (PlanState *) ExecInitAgg((Agg *) node,
343 estate, eflags);
344 break;
345
346 case T_WindowAgg:
347 result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
348 estate, eflags);
349 break;
350
351 case T_Unique:
352 result = (PlanState *) ExecInitUnique((Unique *) node,
353 estate, eflags);
354 break;
355
356 case T_Gather:
357 result = (PlanState *) ExecInitGather((Gather *) node,
358 estate, eflags);
359 break;
360
361 case T_GatherMerge:
362 result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
363 estate, eflags);
364 break;
365
366 case T_Hash:
367 result = (PlanState *) ExecInitHash((Hash *) node,
368 estate, eflags);
369 break;
370
371 case T_SetOp:
372 result = (PlanState *) ExecInitSetOp((SetOp *) node,
373 estate, eflags);
374 break;
375
376 case T_LockRows:
377 result = (PlanState *) ExecInitLockRows((LockRows *) node,
378 estate, eflags);
379 break;
380
381 case T_Limit:
382 result = (PlanState *) ExecInitLimit((Limit *) node,
383 estate, eflags);
384 break;
385
386 default:
387 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
388 result = NULL; /* keep compiler quiet */
389 break;
390 }
391
392 ExecSetExecProcNode(result, result->ExecProcNode);
393
394 /*
395 * Initialize any initPlans present in this node. The planner put them in
396 * a separate list for us.
397 *
398 * The defining characteristic of initplans is that they don't have
399 * arguments, so we don't need to evaluate them (in contrast to
400 * ExecInitSubPlanExpr()).
401 */
402 subps = NIL;
403 foreach(l, node->initPlan)
404 {
405 SubPlan *subplan = (SubPlan *) lfirst(l);
406 SubPlanState *sstate;
407
408 Assert(IsA(subplan, SubPlan));
409 Assert(subplan->args == NIL);
410 sstate = ExecInitSubPlan(subplan, result);
411 subps = lappend(subps, sstate);
412 }
413 result->initPlan = subps;
414
415 /* Set up instrumentation for this node if requested */
416 if (estate->es_instrument)
417 result->instrument = InstrAlloc(1, estate->es_instrument,
418 result->async_capable);
419
420 return result;
421}
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:3281
AppendState * ExecInitAppend(Append *node, EState *estate, int eflags)
Definition nodeAppend.c:111
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:54
GroupState * ExecInitGroup(Group *node, EState *estate, int eflags)
Definition nodeGroup.c:162
HashState * ExecInitHash(Hash *node, EState *estate, int eflags)
Definition nodeHash.c:399
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:573
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:1187
List * initPlan
Definition execnodes.h:1202
bool async_capable
Definition execnodes.h:1219
ExecProcNodeMtd ExecProcNode
Definition execnodes.h:1183
List * initPlan
Definition plannodes.h:240
List * args
Definition primnodes.h:1125

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 2113 of file execTuples.c.

2115{
2116 TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_ops);
2117
2118 return ExecStoreAllNullTuple(slot);
2119}

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

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

◆ ExecInitQual()

ExprState * ExecInitQual ( List qual,
PlanState parent 
)
extern

Definition at line 250 of file execExpr.c.

251{
253 ExprEvalStep scratch = {0};
255
256 /* short-circuit (here and in ExecQual) for empty restriction list */
257 if (qual == NIL)
258 return NULL;
259
260 Assert(IsA(qual, List));
261
263 state->expr = (Expr *) qual;
264 state->parent = parent;
265 state->ext_params = NULL;
266
267 /* mark expression as to be used with ExecQual() */
268 state->flags = EEO_FLAG_IS_QUAL;
269
270 /* Insert setup steps as needed */
272
273 /*
274 * ExecQual() needs to return false for an expression returning NULL. That
275 * allows us to short-circuit the evaluation the first time a NULL is
276 * encountered. As qual evaluation is a hot-path this warrants using a
277 * special opcode for qual evaluation that's simpler than BOOL_AND (which
278 * has more complex NULL handling).
279 */
280 scratch.opcode = EEOP_QUAL;
281
282 /*
283 * We can use ExprState's resvalue/resnull as target for each qual expr.
284 */
285 scratch.resvalue = &state->resvalue;
286 scratch.resnull = &state->resnull;
287
288 foreach_ptr(Expr, node, qual)
289 {
290 /* first evaluate expression */
291 ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
292
293 /* then emit EEOP_QUAL to detect if it's false (or null) */
294 scratch.d.qualexpr.jumpdone = -1;
297 state->steps_len - 1);
298 }
299
300 /* adjust jump targets */
302 {
303 ExprEvalStep *as = &state->steps[jump];
304
305 Assert(as->opcode == EEOP_QUAL);
306 Assert(as->d.qualexpr.jumpdone == -1);
307 as->d.qualexpr.jumpdone = state->steps_len;
308 }
309
310 /*
311 * At the end, we don't need to do anything more. The last qual expr must
312 * have yielded TRUE, and since its result is stored in the desired output
313 * location, we're done.
314 */
315 scratch.opcode = EEOP_DONE_RETURN;
317
319
320 return state;
321}
#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 778 of file execUtils.c.

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

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 885 of file execUtils.c.

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

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 2044 of file execTuples.c.

2045{
2046 TupleTableSlot *slot;
2047
2048 slot = ExecAllocTableSlot(&planstate->state->es_tupleTable,
2049 planstate->ps_ResultTupleDesc, tts_ops, 0);
2050 planstate->ps_ResultTupleSlot = slot;
2051
2052 planstate->resultopsfixed = planstate->ps_ResultTupleDesc != NULL;
2053 planstate->resultops = tts_ops;
2054 planstate->resultopsset = true;
2055}
EState * state
Definition execnodes.h:1179

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,
uint16  flags 
)
extern

◆ ExecInitTableFunctionResult()

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

Definition at line 57 of file execSRF.c.

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

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,
EState estate,
bits32  options,
TupleTableSlot slot,
List arbiterIndexes,
bool specConflict 
)
extern

Definition at line 310 of file execIndexing.c.

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

References Assert, CEOUC_LIVELOCK_PREVENTING_WAIT, CEOUC_NOWAIT, CEOUC_WAIT, check_exclusion_or_unique_constraint(), ExprContext::ecxt_scantuple, EIIT_IS_UPDATE, EIIT_NO_DUPE_ERROR, EIIT_ONLY_SUMMARIZING, 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 4784 of file nodeModifyTable.c.

4786{
4787 if (node->mt_resultOidHash)
4788 {
4789 /* Use the pre-built hash table to locate the rel */
4791
4794 if (mtlookup)
4795 {
4796 if (update_cache)
4797 {
4799 node->mt_lastResultIndex = mtlookup->relationIndex;
4800 }
4801 return node->resultRelInfo + mtlookup->relationIndex;
4802 }
4803 }
4804 else
4805 {
4806 /* With few target rels, just search the ResultRelInfo array */
4807 for (int ndx = 0; ndx < node->mt_nrels; ndx++)
4808 {
4810
4811 if (RelationGetRelid(rInfo->ri_RelationDesc) == resultoid)
4812 {
4813 if (update_cache)
4814 {
4816 node->mt_lastResultIndex = ndx;
4817 }
4818 return rInfo;
4819 }
4820 }
4821 }
4822
4823 if (!missing_ok)
4824 elog(ERROR, "incorrect result relation OID %u", resultoid);
4825 return NULL;
4826}
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:1420
HTAB * mt_resultOidHash
Definition execnodes.h:1442

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 499 of file execSRF.c.

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

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 102 of file execSRF.c.

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

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(), TupleDescFinalize(), 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 328 of file execAmi.c.

329{
330 switch (nodeTag(node))
331 {
332 case T_IndexScanState:
334 break;
335
338 break;
339
342 break;
343
344 case T_MaterialState:
346 break;
347
348 case T_SortState:
349 ExecSortMarkPos((SortState *) node);
350 break;
351
352 case T_ResultState:
354 break;
355
356 default:
357 /* don't make hard error unless caller asks to restore... */
358 elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
359 break;
360 }
361}
#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 636 of file execAmi.c.

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

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:2429
void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
Definition index.c:2670
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:4826

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 747 of file execUtils.c.

748{
749 Relation rel;
750
751 /* Open the relation. */
752 rel = ExecGetRangeTableRelation(estate, scanrelid, false);
753
754 /*
755 * Complain if we're attempting a scan of an unscannable relation, except
756 * when the query won't actually be run. This is a slightly klugy place
757 * to do this, perhaps, but there is no better place.
758 */
759 if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
763 errmsg("materialized view \"%s\" has not been populated",
765 errhint("Use the REFRESH MATERIALIZED VIEW command.")));
766
767 return rel;
768}
#define EXEC_FLAG_WITH_NO_DATA
Definition executor.h:73
#define EXEC_FLAG_EXPLAIN_ONLY
Definition executor.h:67
#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 1875 of file execMain.c.

1877{
1878 ExprContext *econtext;
1879 bool success;
1880
1881 /*
1882 * If first time through, build expression state tree for the partition
1883 * check expression. (In the corner case where the partition check
1884 * expression is empty, ie there's a default partition and nothing else,
1885 * we'll be fooled into executing this code each time through. But it's
1886 * pretty darn cheap in that case, so we don't worry about it.)
1887 */
1888 if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1889 {
1890 /*
1891 * Ensure that the qual tree and prepared expression are in the
1892 * query-lifespan context.
1893 */
1895 List *qual = RelationGetPartitionQual(resultRelInfo->ri_RelationDesc);
1896
1897 resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1899 }
1900
1901 /*
1902 * We will use the EState's per-tuple context for evaluating constraint
1903 * expressions (creating it if it's not already there).
1904 */
1905 econtext = GetPerTupleExprContext(estate);
1906
1907 /* Arrange for econtext's scan tuple to be the tuple under test */
1908 econtext->ecxt_scantuple = slot;
1909
1910 /*
1911 * As in case of the cataloged constraints, we treat a NULL result as
1912 * success here, not a failure.
1913 */
1914 success = ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext);
1915
1916 /* if asked to emit error, don't actually return on failure */
1917 if (!success && emitError)
1918 ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
1919
1920 return success;
1921}
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition execExpr.c:905
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition execExpr.c:849
void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition execMain.c:1928
static bool success
Definition initdb.c:188
List * RelationGetPartitionQual(Relation rel)
Definition partcache.c:277
ExprState * ri_PartitionCheckExpr
Definition execnodes.h:604

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 1928 of file execMain.c.

1931{
1933 TupleDesc tupdesc;
1934 char *val_desc;
1936
1937 /*
1938 * If the tuple has been routed, it's been converted to the partition's
1939 * rowtype, which might differ from the root table's. We must convert it
1940 * back to the root table's rowtype so that val_desc in the error message
1941 * matches the input tuple.
1942 */
1943 if (resultRelInfo->ri_RootResultRelInfo)
1944 {
1945 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1947 AttrMap *map;
1948
1949 root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
1950 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1951
1953 /* a reverse map */
1954 map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc, false);
1955
1956 /*
1957 * Partition-specific slot's tupdesc can't be changed, so allocate a
1958 * new one.
1959 */
1960 if (map != NULL)
1961 slot = execute_attr_map_slot(map, slot,
1962 MakeTupleTableSlot(tupdesc, &TTSOpsVirtual, 0));
1964 ExecGetUpdatedCols(rootrel, estate));
1965 }
1966 else
1967 {
1969 tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1970 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1971 ExecGetUpdatedCols(resultRelInfo, estate));
1972 }
1973
1975 slot,
1976 tupdesc,
1978 64);
1979 ereport(ERROR,
1981 errmsg("new row for relation \"%s\" violates partition constraint",
1983 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1984 errtable(resultRelInfo->ri_RelationDesc)));
1985}
int errtable(Relation rel)
Definition relcache.c:6062

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

850{
851 ExprState *result;
852 MemoryContext oldcontext;
853
854 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
855
856 qual = (List *) expression_planner((Expr *) qual);
857
858 result = ExecInitCheck(qual, NULL);
859
860 MemoryContextSwitchTo(oldcontext);
861
862 return result;
863}
ExprState * ExecInitCheck(List *qual, PlanState *parent)
Definition execExpr.c:336
Expr * expression_planner(Expr *expr)
Definition planner.c:6819

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

Referenced by ExecPartitionCheck().

◆ ExecPrepareExpr()

ExprState * ExecPrepareExpr ( Expr node,
EState estate 
)
extern

◆ ExecPrepareExprList()

List * ExecPrepareExprList ( List nodes,
EState estate 
)
extern

Definition at line 872 of file execExpr.c.

873{
874 List *result = NIL;
875 MemoryContext oldcontext;
876 ListCell *lc;
877
878 /* Ensure that the list cell nodes are in the right context too */
879 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
880
881 foreach(lc, nodes)
882 {
883 Expr *e = (Expr *) lfirst(lc);
884
885 result = lappend(result, ExecPrepareExpr(e, estate));
886 }
887
888 MemoryContextSwitchTo(oldcontext);
889
890 return result;
891}
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition execExpr.c:786

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

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

◆ ExecPrepareExprWithContext()

ExprState * ExecPrepareExprWithContext ( Expr node,
EState estate,
Node escontext 
)
extern

Definition at line 798 of file execExpr.c.

799{
800 ExprState *result;
801 MemoryContext oldcontext;
802
803 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
804
805 node = expression_planner(node);
806
807 result = ExecInitExprWithContext(node, NULL, escontext);
808
809 MemoryContextSwitchTo(oldcontext);
810
811 return result;
812}

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

Referenced by ATExecAddColumn(), and ExecPrepareExpr().

◆ ExecPrepareQual()

ExprState * ExecPrepareQual ( List qual,
EState estate 
)
extern

Definition at line 826 of file execExpr.c.

827{
828 ExprState *result;
829 MemoryContext oldcontext;
830
831 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
832
833 qual = (List *) expression_planner((Expr *) qual);
834
835 result = ExecInitQual(qual, NULL);
836
837 MemoryContextSwitchTo(oldcontext);
838
839 return result;
840}
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:250

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

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

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

◆ ExecQualAndReset()

static bool ExecQualAndReset ( ExprState state,
ExprContext econtext 
)
inlinestatic

◆ ExecRelationIsTargetRelation()

bool ExecRelationIsTargetRelation ( EState estate,
Index  scanrelid 
)
extern

Definition at line 734 of file execUtils.c.

735{
736 return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
737}
bool list_member_int(const List *list, int datum)
Definition list.c:702
List * resultRelations
Definition plannodes.h:122

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 2113 of file execMain.c.

2115{
2116 Relation rel = resultRelInfo->ri_RelationDesc;
2117 ExprContext *econtext;
2119
2120 /*
2121 * We implement this by building a NullTest node for each virtual
2122 * generated column, which we cache in resultRelInfo, and running those
2123 * through ExecCheck().
2124 */
2125 if (resultRelInfo->ri_GenVirtualNotNullConstraintExprs == NULL)
2126 {
2130
2132 {
2135
2136 /* "generated_expression IS NOT NULL" check. */
2139 nnulltest->nulltesttype = IS_NOT_NULL;
2140 nnulltest->argisrow = false;
2141 nnulltest->location = -1;
2142
2143 resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i] =
2144 ExecPrepareExpr((Expr *) nnulltest, estate);
2145 }
2147 }
2148
2149 /*
2150 * We will use the EState's per-tuple context for evaluating virtual
2151 * generated column not null constraint expressions (creating it if it's
2152 * not already there).
2153 */
2154 econtext = GetPerTupleExprContext(estate);
2155
2156 /* Arrange for econtext's scan tuple to be the tuple under test */
2157 econtext->ecxt_scantuple = slot;
2158
2159 /* And evaluate the check constraints for virtual generated column */
2161 {
2163 ExprState *exprstate = resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i];
2164
2165 Assert(exprstate != NULL);
2166 if (!ExecCheck(exprstate, econtext))
2167 return attnum;
2168 }
2169
2170 /* InvalidAttrNumber result means no error */
2171 return InvalidAttrNumber;
2172}
@ IS_NOT_NULL
Definition primnodes.h:1979
Node * build_generation_expression(Relation rel, int attrno)
ExprState ** ri_GenVirtualNotNullConstraintExprs
Definition execnodes.h:573

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 78 of file execAmi.c.

79{
80 /* If collecting timing stats, update them */
81 if (node->instrument)
83
84 /*
85 * If we have changed parameters, propagate that info.
86 *
87 * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
88 * corresponding to the output param(s) that the InitPlan will update.
89 * Since we make only one pass over the list, that means that an InitPlan
90 * can depend on the output param(s) of a sibling InitPlan only if that
91 * sibling appears earlier in the list. This is workable for now given
92 * the limited ways in which one InitPlan could depend on another, but
93 * eventually we might need to work harder (or else make the planner
94 * enlarge the extParam/allParam sets to include the params of depended-on
95 * InitPlans).
96 */
97 if (node->chgParam != NULL)
98 {
99 ListCell *l;
100
101 foreach(l, node->initPlan)
102 {
103 SubPlanState *sstate = (SubPlanState *) lfirst(l);
104 PlanState *splan = sstate->planstate;
105
106 if (splan->plan->extParam != NULL) /* don't care about child
107 * local Params */
108 UpdateChangedParamSet(splan, node->chgParam);
109 if (splan->chgParam != NULL)
110 ExecReScanSetParamPlan(sstate, node);
111 }
112 foreach(l, node->subPlan)
113 {
114 SubPlanState *sstate = (SubPlanState *) lfirst(l);
115 PlanState *splan = sstate->planstate;
116
117 if (splan->plan->extParam != NULL)
118 UpdateChangedParamSet(splan, node->chgParam);
119 }
120 /* Well. Now set chgParam for child trees. */
121 if (outerPlanState(node) != NULL)
123 if (innerPlanState(node) != NULL)
125 }
126
127 /* Call expression callbacks */
128 if (node->ps_ExprContext)
130
131 /* And do node-type-specific processing */
132 switch (nodeTag(node))
133 {
134 case T_ResultState:
136 break;
137
140 break;
141
144 break;
145
146 case T_AppendState:
148 break;
149
152 break;
153
156 break;
157
158 case T_BitmapAndState:
160 break;
161
162 case T_BitmapOrState:
164 break;
165
166 case T_SeqScanState:
168 break;
169
172 break;
173
174 case T_GatherState:
176 break;
177
180 break;
181
182 case T_IndexScanState:
184 break;
185
188 break;
189
192 break;
193
196 break;
197
198 case T_TidScanState:
200 break;
201
204 break;
205
208 break;
209
212 break;
213
216 break;
217
220 break;
221
222 case T_CteScanState:
224 break;
225
228 break;
229
232 break;
233
236 break;
237
240 break;
241
242 case T_NestLoopState:
244 break;
245
246 case T_MergeJoinState:
248 break;
249
250 case T_HashJoinState:
252 break;
253
254 case T_MaterialState:
256 break;
257
258 case T_MemoizeState:
260 break;
261
262 case T_SortState:
263 ExecReScanSort((SortState *) node);
264 break;
265
268 break;
269
270 case T_GroupState:
271 ExecReScanGroup((GroupState *) node);
272 break;
273
274 case T_AggState:
275 ExecReScanAgg((AggState *) node);
276 break;
277
278 case T_WindowAggState:
280 break;
281
282 case T_UniqueState:
284 break;
285
286 case T_HashState:
287 ExecReScanHash((HashState *) node);
288 break;
289
290 case T_SetOpState:
291 ExecReScanSetOp((SetOpState *) node);
292 break;
293
294 case T_LockRowsState:
296 break;
297
298 case T_LimitState:
299 ExecReScanLimit((LimitState *) node);
300 break;
301
302 default:
303 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
304 break;
305 }
306
307 if (node->chgParam != NULL)
308 {
309 bms_free(node->chgParam);
310 node->chgParam = NULL;
311 }
312}
void ReScanExprContext(ExprContext *econtext)
Definition execUtils.c:448
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition execUtils.c:915
void InstrEndLoop(Instrumentation *instr)
Definition instrument.c:144
void ExecReScanAgg(AggState *node)
Definition nodeAgg.c:4462
void ExecReScanAppend(AppendState *node)
Definition nodeAppend.c:423
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:443
void ExecReScanGroup(GroupState *node)
Definition nodeGroup.c:236
void ExecReScanHash(HashState *node)
Definition nodeHash.c:2407
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:704
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:1204
Bitmapset * extParam
Definition plannodes.h:253
PlanState * planstate
Definition execnodes.h:1025

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 377 of file execAmi.c.

378{
379 switch (nodeTag(node))
380 {
381 case T_IndexScanState:
383 break;
384
387 break;
388
391 break;
392
393 case T_MaterialState:
395 break;
396
397 case T_SortState:
398 ExecSortRestrPos((SortState *) node);
399 break;
400
401 case T_ResultState:
403 break;
404
405 default:
406 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
407 break;
408 }
409}
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:161
struct EPQState * es_epq_active
Definition execnodes.h:754
ExprState * qual
Definition execnodes.h:1198

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 431 of file execProcnode.c.

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

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 849 of file execProcnode.c.

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

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 773 of file execProcnode.c.

774{
776}
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 992 of file execReplication.c.

995{
996 bool skip_tuple = false;
997 Relation rel = resultRelInfo->ri_RelationDesc;
998 ItemPointer tid = &searchslot->tts_tid;
999
1001
1002 /* BEFORE ROW DELETE Triggers */
1003 if (resultRelInfo->ri_TrigDesc &&
1004 resultRelInfo->ri_TrigDesc->trig_delete_before_row)
1005 {
1006 skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
1007 tid, NULL, NULL, NULL, NULL, false);
1008 }
1009
1010 if (!skip_tuple)
1011 {
1012 /* OK, delete the tuple */
1013 simple_table_tuple_delete(rel, tid, estate->es_snapshot);
1014
1015 /* AFTER ROW DELETE Triggers */
1016 ExecARDeleteTriggers(estate, resultRelInfo,
1017 tid, NULL, NULL, false);
1018 }
1019}
TriggerDesc * ri_TrigDesc
Definition execnodes.h:527
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:2803
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:2703

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)
849 {
850 bits32 flags;
851
852 if (conflictindexes != NIL)
853 flags = EIIT_NO_DUPE_ERROR;
854 else
855 flags = 0;
857 estate, flags,
858 slot, conflictindexes,
859 &conflict);
860 }
861
862 /*
863 * Checks the conflict indexes to fetch the conflicting local row and
864 * reports the conflict. We perform this check here, instead of
865 * performing an additional index scan before the actual insertion and
866 * reporting the conflict if any conflicting rows are found. This is
867 * to avoid the overhead of executing the extra scan for each INSERT
868 * operation, even when no conflict arises, which could introduce
869 * significant overhead to replication, particularly in cases where
870 * conflicts are rare.
871 *
872 * XXX OTOH, this could lead to clean-up effort for dead tuples added
873 * in heap and index in case of conflicts. But as conflicts shouldn't
874 * be a frequent thing so we preferred to save the performance
875 * overhead of extra scan before each insertion.
876 */
877 if (conflict)
878 CheckAndReportConflict(resultRelInfo, estate, CT_INSERT_EXISTS,
879 recheckIndexes, NULL, slot);
880
881 /* AFTER ROW INSERT Triggers */
882 ExecARInsertTriggers(estate, resultRelInfo, slot,
884
885 /*
886 * XXX we should in theory pass a TransitionCaptureState object to the
887 * above to capture transition tuples, but after statement triggers
888 * don't actually get fired by replication yet anyway
889 */
890
892 }
893}
uint32 bits32
Definition c.h:627
@ CT_INSERT_EXISTS
Definition conflict.h:34
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, EState *estate, bits32 flags, TupleTableSlot *slot, List *arbiterIndexes, bool *specConflict)
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition execMain.c:1875
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition execMain.c:1999
static void CheckAndReportConflict(ResultRelInfo *resultRelInfo, EState *estate, ConflictType type, List *recheckIndexes, TupleTableSlot *searchslot, TupleTableSlot *remoteslot)
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
TupleDesc rd_att
Definition rel.h:112
List * ri_onConflictArbiterIndexes
Definition execnodes.h:592
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:2467
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition trigger.c:2545

References Assert, CheckAndReportConflict(), CheckCmdReplicaIdentity(), CMD_INSERT, TupleDescData::constr, CT_INSERT_EXISTS, EIIT_NO_DUPE_ERROR, 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 902 of file execReplication.c.

905{
906 bool skip_tuple = false;
907 Relation rel = resultRelInfo->ri_RelationDesc;
908 ItemPointer tid = &(searchslot->tts_tid);
909
910 /*
911 * We support only non-system tables, with
912 * check_publication_add_relation() accountable.
913 */
914 Assert(rel->rd_rel->relkind == RELKIND_RELATION);
916
918
919 /* BEFORE ROW UPDATE Triggers */
920 if (resultRelInfo->ri_TrigDesc &&
921 resultRelInfo->ri_TrigDesc->trig_update_before_row)
922 {
923 if (!ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
924 tid, NULL, slot, NULL, NULL, false))
925 skip_tuple = true; /* "do nothing" */
926 }
927
928 if (!skip_tuple)
929 {
933 bool conflict = false;
934
935 /* Compute stored generated columns */
936 if (rel->rd_att->constr &&
938 ExecComputeStoredGenerated(resultRelInfo, estate, slot,
939 CMD_UPDATE);
940
941 /* Check the constraints of the tuple */
942 if (rel->rd_att->constr)
943 ExecConstraints(resultRelInfo, slot, estate);
944 if (rel->rd_rel->relispartition)
945 ExecPartitionCheck(resultRelInfo, slot, estate, true);
946
947 simple_table_tuple_update(rel, tid, slot, estate->es_snapshot,
949
951
952 if (resultRelInfo->ri_NumIndices > 0 && (update_indexes != TU_None))
953 {
954 bits32 flags = EIIT_IS_UPDATE;
955
956 if (conflictindexes != NIL)
957 flags |= EIIT_NO_DUPE_ERROR;
959 flags |= EIIT_ONLY_SUMMARIZING;
961 estate, flags,
962 slot, conflictindexes,
963 &conflict);
964 }
965
966 /*
967 * Refer to the comments above the call to CheckAndReportConflict() in
968 * ExecSimpleRelationInsert to understand why this check is done at
969 * this point.
970 */
971 if (conflict)
972 CheckAndReportConflict(resultRelInfo, estate, CT_UPDATE_EXISTS,
974
975 /* AFTER ROW UPDATE Triggers */
976 ExecARUpdateTriggers(estate, resultRelInfo,
977 NULL, NULL,
978 tid, NULL, slot,
979 recheckIndexes, NULL, false);
980
982 }
983}
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:2973
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:3146

References Assert, CheckAndReportConflict(), CheckCmdReplicaIdentity(), CMD_UPDATE, TupleDescData::constr, CT_UPDATE_EXISTS, EIIT_IS_UPDATE, EIIT_NO_DUPE_ERROR, EIIT_ONLY_SUMMARIZING, 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 512 of file execAmi.c.

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

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 419 of file execAmi.c.

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

1181{
1182 /* This used to be more complex, but fjoins are dead */
1183 return list_length(targetlist);
1184}

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:1505
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition lsyscache.c:577

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 2259 of file execTuples.c.

2260{
2262 ListCell *lc;
2263 int cur_resno = 1;
2264
2266
2267 foreach(lc, exprList)
2268 {
2269 Node *e = lfirst(lc);
2270
2272 cur_resno,
2273 NULL,
2274 exprType(e),
2275 exprTypmod(e),
2276 0);
2278 cur_resno,
2279 exprCollation(e));
2280 cur_resno++;
2281 }
2282
2284
2285 return typeInfo;
2286}
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition tupdesc.c:1081

References CreateTemplateTupleDesc(), exprCollation(), exprType(), exprTypmod(), fb(), lfirst, list_length(), TupleDescFinalize(), 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 2294 of file execTuples.c.

2295{
2296 int colno = 0;
2297 ListCell *lc;
2298
2299 /* It's only OK to change col names in a not-yet-blessed RECORD type */
2300 Assert(typeInfo->tdtypeid == RECORDOID);
2301 Assert(typeInfo->tdtypmod < 0);
2302
2303 foreach(lc, namesList)
2304 {
2305 char *cname = strVal(lfirst(lc));
2306 Form_pg_attribute attr;
2307
2308 /* Guard against too-long names list (probably can't happen) */
2309 if (colno >= typeInfo->natts)
2310 break;
2311 attr = TupleDescAttr(typeInfo, colno);
2312 colno++;
2313
2314 /*
2315 * Do nothing for empty aliases or dropped columns (these cases
2316 * probably can't arise in RECORD types, either)
2317 */
2318 if (cname[0] == '\0' || attr->attisdropped)
2319 continue;
2320
2321 /* OK, assign the column name */
2322 namestrcpy(&(attr->attname), cname);
2323 }
2324}
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 2549 of file execMain.c.

2550{
2552 Bitmapset *updatedCols;
2553
2554 /*
2555 * Compute lock mode to use. If columns that are part of the key have not
2556 * been modified, then we can use a weaker lock, allowing for better
2557 * concurrency.
2558 */
2559 updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2560 keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2562
2563 if (bms_overlap(keyCols, updatedCols))
2564 return LockTupleExclusive;
2565
2567}
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:575
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1423
@ LockTupleExclusive
Definition lockoptions.h:59
@ LockTupleNoKeyExclusive
Definition lockoptions.h:57
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition relcache.c:5293
@ 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 941 of file execUtils.c.

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

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 468 of file execMain.c.

469{
471 (*ExecutorEnd_hook) (queryDesc);
472 else
473 standard_ExecutorEnd(queryDesc);
474}
ExecutorEnd_hook_type ExecutorEnd_hook
Definition execMain.c:73
void standard_ExecutorEnd(QueryDesc *queryDesc)
Definition execMain.c:477

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 408 of file execMain.c.

409{
411 (*ExecutorFinish_hook) (queryDesc);
412 else
413 standard_ExecutorFinish(queryDesc);
414}
ExecutorFinish_hook_type ExecutorFinish_hook
Definition execMain.c:72
void standard_ExecutorFinish(QueryDesc *queryDesc)
Definition execMain.c:417

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 538 of file execMain.c.

539{
540 EState *estate;
541 MemoryContext oldcontext;
542
543 /* sanity checks */
544 Assert(queryDesc != NULL);
545
546 estate = queryDesc->estate;
547
548 Assert(estate != NULL);
549
550 /* It's probably not sensible to rescan updating queries */
551 Assert(queryDesc->operation == CMD_SELECT);
552
553 /*
554 * Switch into per-query memory context
555 */
556 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
557
558 /*
559 * rescan plan
560 */
561 ExecReScan(queryDesc->planstate);
562
563 MemoryContextSwitchTo(oldcontext);
564}
void ExecReScan(PlanState *node)
Definition execAmi.c:78
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 299 of file execMain.c.

301{
303 (*ExecutorRun_hook) (queryDesc, direction, count);
304 else
305 standard_ExecutorRun(queryDesc, direction, count);
306}
ExecutorRun_hook_type ExecutorRun_hook
Definition execMain.c:71
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition execMain.c:309

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 124 of file execMain.c.

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

2249{
2250 Relation rel = resultRelInfo->ri_RelationDesc;
2251 TupleDesc tupdesc = RelationGetDescr(rel);
2252 ExprContext *econtext;
2253 ListCell *l1,
2254 *l2;
2255
2256 /*
2257 * We will use the EState's per-tuple context for evaluating constraint
2258 * expressions (creating it if it's not already there).
2259 */
2260 econtext = GetPerTupleExprContext(estate);
2261
2262 /* Arrange for econtext's scan tuple to be the tuple under test */
2263 econtext->ecxt_scantuple = slot;
2264
2265 /* Check each of the constraints */
2266 forboth(l1, resultRelInfo->ri_WithCheckOptions,
2267 l2, resultRelInfo->ri_WithCheckOptionExprs)
2268 {
2270 ExprState *wcoExpr = (ExprState *) lfirst(l2);
2271
2272 /*
2273 * Skip any WCOs which are not the kind we are looking for at this
2274 * time.
2275 */
2276 if (wco->kind != kind)
2277 continue;
2278
2279 /*
2280 * WITH CHECK OPTION checks are intended to ensure that the new tuple
2281 * is visible (in the case of a view) or that it passes the
2282 * 'with-check' policy (in the case of row security). If the qual
2283 * evaluates to NULL or FALSE, then the new tuple won't be included in
2284 * the view or doesn't pass the 'with-check' policy for the table.
2285 */
2286 if (!ExecQual(wcoExpr, econtext))
2287 {
2288 char *val_desc;
2290
2291 switch (wco->kind)
2292 {
2293 /*
2294 * For WITH CHECK OPTIONs coming from views, we might be
2295 * able to provide the details on the row, depending on
2296 * the permissions on the relation (that is, if the user
2297 * could view it directly anyway). For RLS violations, we
2298 * don't include the data since we don't know if the user
2299 * should be able to view the tuple as that depends on the
2300 * USING policy.
2301 */
2302 case WCO_VIEW_CHECK:
2303 /* See the comment in ExecConstraints(). */
2304 if (resultRelInfo->ri_RootResultRelInfo)
2305 {
2306 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2308 AttrMap *map;
2309
2310 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2311 /* a reverse map */
2313 tupdesc,
2314 false);
2315
2316 /*
2317 * Partition-specific slot's tupdesc can't be changed,
2318 * so allocate a new one.
2319 */
2320 if (map != NULL)
2321 slot = execute_attr_map_slot(map, slot,
2322 MakeTupleTableSlot(tupdesc, &TTSOpsVirtual, 0));
2323
2325 ExecGetUpdatedCols(rootrel, estate));
2326 rel = rootrel->ri_RelationDesc;
2327 }
2328 else
2329 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2330 ExecGetUpdatedCols(resultRelInfo, estate));
2332 slot,
2333 tupdesc,
2335 64);
2336
2337 ereport(ERROR,
2339 errmsg("new row violates check option for view \"%s\"",
2340 wco->relname),
2341 val_desc ? errdetail("Failing row contains %s.",
2342 val_desc) : 0));
2343 break;
2346 if (wco->polname != NULL)
2347 ereport(ERROR,
2349 errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
2350 wco->polname, wco->relname)));
2351 else
2352 ereport(ERROR,
2354 errmsg("new row violates row-level security policy for table \"%s\"",
2355 wco->relname)));
2356 break;
2359 if (wco->polname != NULL)
2360 ereport(ERROR,
2362 errmsg("target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2363 wco->polname, wco->relname)));
2364 else
2365 ereport(ERROR,
2367 errmsg("target row violates row-level security policy (USING expression) for table \"%s\"",
2368 wco->relname)));
2369 break;
2371 if (wco->polname != NULL)
2372 ereport(ERROR,
2374 errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2375 wco->polname, wco->relname)));
2376 else
2377 ereport(ERROR,
2379 errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
2380 wco->relname)));
2381 break;
2382 default:
2383 elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
2384 break;
2385 }
2386 }
2387 }
2388}
@ 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:561
List * ri_WithCheckOptionExprs
Definition execnodes.h:564

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(), ExecOnConflictSelect(), 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 197 of file execUtils.c.

198{
199 /*
200 * Shut down and free any remaining ExprContexts. We do this explicitly
201 * to ensure that any remaining shutdown callbacks get called (since they
202 * might need to release resources that aren't simply memory within the
203 * per-query memory context).
204 */
205 while (estate->es_exprcontexts)
206 {
207 /*
208 * XXX: seems there ought to be a faster way to implement this than
209 * repeated list_delete(), no?
210 */
212 true);
213 /* FreeExprContext removed the list link for us */
214 }
215
216 /* release JIT context, if allocated */
217 if (estate->es_jit)
218 {
220 estate->es_jit = NULL;
221 }
222
223 /* release partition directory, if allocated */
224 if (estate->es_partition_directory)
225 {
228 }
229
230 /*
231 * Free the per-query memory context, thereby releasing all working
232 * memory, including the EState node itself.
233 */
235}
void FreeExprContext(ExprContext *econtext, bool isCommit)
Definition execUtils.c:421
void jit_release_context(JitContext *context)
Definition jit.c:138
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 421 of file execUtils.c.

422{
423 EState *estate;
424
425 /* Call any registered callbacks */
426 ShutdownExprContext(econtext, isCommit);
427 /* And clean up the memory used */
429 /* Unlink self from owning EState, if any */
430 estate = econtext->ecxt_estate;
431 if (estate)
433 econtext);
434 /* And delete the ExprContext node */
435 pfree(econtext);
436}
static void ShutdownExprContext(ExprContext *econtext, bool isCommit)
Definition execUtils.c:1025
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 1066 of file execUtils.c.

1067{
1069 Datum result;
1070 Oid tupType;
1072 TupleDesc tupDesc;
1074 int i;
1075
1076 if (attname == NULL)
1077 elog(ERROR, "invalid attribute name");
1078
1079 if (isNull == NULL)
1080 elog(ERROR, "a NULL isNull pointer was passed");
1081
1082 if (tuple == NULL)
1083 {
1084 /* Kinda bogus but compatible with old behavior... */
1085 *isNull = true;
1086 return (Datum) 0;
1087 }
1088
1092
1094 for (i = 0; i < tupDesc->natts; i++)
1095 {
1097
1098 if (namestrcmp(&(att->attname), attname) == 0)
1099 {
1100 attrno = att->attnum;
1101 break;
1102 }
1103 }
1104
1106 elog(ERROR, "attribute \"%s\" does not exist", attname);
1107
1108 /*
1109 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1110 * the fields in the struct just in case user tries to inspect system
1111 * columns.
1112 */
1114 ItemPointerSetInvalid(&(tmptup.t_self));
1115 tmptup.t_tableOid = InvalidOid;
1116 tmptup.t_data = tuple;
1117
1118 result = heap_getattr(&tmptup,
1119 attrno,
1120 tupDesc,
1121 isNull);
1122
1123 ReleaseTupleDesc(tupDesc);
1124
1125 return result;
1126}
int32_t int32
Definition c.h:614
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:238
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition typcache.c:1947

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 1129 of file execUtils.c.

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

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 1262 of file execMain.c.

1267{
1268 MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1269 resultRelInfo->type = T_ResultRelInfo;
1270 resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1271 resultRelInfo->ri_RelationDesc = resultRelationDesc;
1272 resultRelInfo->ri_NumIndices = 0;
1273 resultRelInfo->ri_IndexRelationDescs = NULL;
1274 resultRelInfo->ri_IndexRelationInfo = NULL;
1275 resultRelInfo->ri_needLockTagTuple =
1277 /* make a copy so as not to depend on relcache info not changing... */
1278 resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1279 if (resultRelInfo->ri_TrigDesc)
1280 {
1281 int n = resultRelInfo->ri_TrigDesc->numtriggers;
1282
1283 resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1285 resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1287 if (instrument_options)
1288 resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options, false);
1289 }
1290 else
1291 {
1292 resultRelInfo->ri_TrigFunctions = NULL;
1293 resultRelInfo->ri_TrigWhenExprs = NULL;
1294 resultRelInfo->ri_TrigInstrument = NULL;
1295 }
1296 if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1298 else
1299 resultRelInfo->ri_FdwRoutine = NULL;
1300
1301 /* The following fields are set later if needed */
1302 resultRelInfo->ri_RowIdAttNo = 0;
1303 resultRelInfo->ri_extraUpdatedCols = NULL;
1304 resultRelInfo->ri_projectNew = NULL;
1305 resultRelInfo->ri_newTupleSlot = NULL;
1306 resultRelInfo->ri_oldTupleSlot = NULL;
1307 resultRelInfo->ri_projectNewInfoValid = false;
1308 resultRelInfo->ri_FdwState = NULL;
1309 resultRelInfo->ri_usesFdwDirectModify = false;
1310 resultRelInfo->ri_CheckConstraintExprs = NULL;
1312 resultRelInfo->ri_GeneratedExprsI = NULL;
1313 resultRelInfo->ri_GeneratedExprsU = NULL;
1314 resultRelInfo->ri_projectReturning = NULL;
1315 resultRelInfo->ri_onConflictArbiterIndexes = NIL;
1316 resultRelInfo->ri_onConflict = NULL;
1317 resultRelInfo->ri_ReturningSlot = NULL;
1318 resultRelInfo->ri_TrigOldSlot = NULL;
1319 resultRelInfo->ri_TrigNewSlot = NULL;
1320 resultRelInfo->ri_AllNullSlot = NULL;
1321 resultRelInfo->ri_MergeActions[MERGE_WHEN_MATCHED] = NIL;
1324 resultRelInfo->ri_MergeJoinCondition = NULL;
1325
1326 /*
1327 * Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
1328 * non-NULL partition_root_rri. For child relations that are part of the
1329 * initial query rather than being dynamically added by tuple routing,
1330 * this field is filled in ExecInitModifyTable().
1331 */
1333 /* Set by ExecGetRootToChildMap */
1334 resultRelInfo->ri_RootToChildMap = NULL;
1335 resultRelInfo->ri_RootToChildMapValid = false;
1336 /* Set by ExecInitRoutingInfo */
1337 resultRelInfo->ri_PartitionTupleSlot = NULL;
1338 resultRelInfo->ri_ChildToRootMap = NULL;
1339 resultRelInfo->ri_ChildToRootMapValid = false;
1340 resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
1341}
#define MemSet(start, val, len)
Definition c.h:1109
@ MERGE_WHEN_NOT_MATCHED_BY_TARGET
Definition primnodes.h:2025
@ MERGE_WHEN_NOT_MATCHED_BY_SOURCE
Definition primnodes.h:2024
@ MERGE_WHEN_MATCHED
Definition primnodes.h:2023
OnConflictActionState * ri_onConflict
Definition execnodes.h:595
ExprState ** ri_CheckConstraintExprs
Definition execnodes.h:567
TupleTableSlot * ri_PartitionTupleSlot
Definition execnodes.h:631
bool ri_projectNewInfoValid
Definition execnodes.h:521
Instrumentation * ri_TrigInstrument
Definition execnodes.h:536
ExprState * ri_MergeJoinCondition
Definition execnodes.h:601
TupleTableSlot * ri_ReturningSlot
Definition execnodes.h:539
TupleTableSlot * ri_oldTupleSlot
Definition execnodes.h:519
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition execnodes.h:634
TupleTableSlot * ri_AllNullSlot
Definition execnodes.h:542
Bitmapset * ri_extraUpdatedCols
Definition execnodes.h:510
ExprState ** ri_GeneratedExprsI
Definition execnodes.h:578
void * ri_FdwState
Definition execnodes.h:548
List * ri_MergeActions[NUM_MERGE_MATCH_KINDS]
Definition execnodes.h:598
TupleTableSlot * ri_newTupleSlot
Definition execnodes.h:517
ProjectionInfo * ri_projectNew
Definition execnodes.h:515
NodeTag type
Definition execnodes.h:486
ProjectionInfo * ri_projectReturning
Definition execnodes.h:589
ExprState ** ri_GeneratedExprsU
Definition execnodes.h:579
ExprState ** ri_TrigWhenExprs
Definition execnodes.h:533
FmgrInfo * ri_TrigFunctions
Definition execnodes.h:530
bool ri_usesFdwDirectModify
Definition execnodes.h:551
AttrNumber ri_RowIdAttNo
Definition execnodes.h:507
TupleTableSlot * ri_TrigNewSlot
Definition execnodes.h:541
TupleTableSlot * ri_TrigOldSlot
Definition execnodes.h:540
int numtriggers
Definition reltrigger.h:50
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition trigger.c:2092

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 463 of file execUtils.c.

464{
465 if (estate->es_per_tuple_exprcontext == NULL)
467
468 return estate->es_per_tuple_exprcontext;
469}

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

◆ MultiExecProcNode()

Node * MultiExecProcNode ( PlanState node)
extern

Definition at line 508 of file execProcnode.c.

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

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 968 of file execUtils.c.

971{
973
974 /* Save the info in appropriate memory context */
977 sizeof(ExprContext_CB));
978
980 ecxt_callback->arg = arg;
981
982 /* link to front of list for appropriate execution order */
983 ecxt_callback->next = econtext->ecxt_callbacks;
984 econtext->ecxt_callbacks = ecxt_callback;
985}
Datum arg
Definition elog.c:1322
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
ExprContextCallbackFunction function
Definition execnodes.h:251

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:645

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:1004
static void table_rescan(TableScanDesc scan, ScanKeyData *key)
Definition tableam.h:1013
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition tableam.h:1039
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key)
Definition tableam.h:896

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:738
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:40
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:1570
#define TransactionIdIsValid(xid)
Definition transam.h:41
CommandId GetCurrentCommandId(bool used)
Definition xact.c:831

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 448 of file execUtils.c.

449{
450 /* Call any registered callbacks */
451 ShutdownExprContext(econtext, true);
452 /* And clean up the memory used */
454}

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 477 of file execMain.c.

478{
479 EState *estate;
480 MemoryContext oldcontext;
481
482 /* sanity checks */
483 Assert(queryDesc != NULL);
484
485 estate = queryDesc->estate;
486
487 Assert(estate != NULL);
488
489 if (estate->es_parallel_workers_to_launch > 0)
492
493 /*
494 * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This
495 * Assert is needed because ExecutorFinish is new as of 9.1, and callers
496 * might forget to call it.
497 */
498 Assert(estate->es_finished ||
500
501 /*
502 * Switch into per-query memory context to run ExecEndPlan
503 */
504 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
505
506 ExecEndPlan(queryDesc->planstate, estate);
507
508 /* do away with our snapshots */
511
512 /*
513 * Must switch out of context before destroying it
514 */
515 MemoryContextSwitchTo(oldcontext);
516
517 /*
518 * Release EState and per-query memory context. This should release
519 * everything the executor has allocated.
520 */
521 FreeExecutorState(estate);
522
523 /* Reset queryDesc fields that no longer point to anything */
524 queryDesc->tupDesc = NULL;
525 queryDesc->estate = NULL;
526 queryDesc->planstate = NULL;
527 queryDesc->totaltime = NULL;
528}
static void ExecEndPlan(PlanState *planstate, EState *estate)
Definition execMain.c:1555
int64 PgStat_Counter
Definition pgstat.h:70
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 417 of file execMain.c.

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

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 309 of file execMain.c.

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

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

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

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

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

180{
181 return entry->firstTuple;
182}

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

171{
172 return sizeof(TupleHashEntryData);
173}

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 994 of file execUtils.c.

997{
1000
1001 prev_callback = &econtext->ecxt_callbacks;
1002
1003 while ((ecxt_callback = *prev_callback) != NULL)
1004 {
1005 if (ecxt_callback->function == function && ecxt_callback->arg == arg)
1006 {
1009 }
1010 else
1012 }
1013}
struct ExprContext_CB * next
Definition execnodes.h:250

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 915 of file execUtils.c.

916{
918
919 /*
920 * The plan node only depends on params listed in its allParam set. Don't
921 * include anything else into its chgParam set.
922 */
924 node->chgParam = bms_join(node->chgParam, parmset);
925}
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:292
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition bitmapset.c:1214
Bitmapset * allParam
Definition plannodes.h:254

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 76 of file execMain.c.

Referenced by _PG_init(), and ExecCheckPermissions().

◆ ExecutorEnd_hook

PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook
extern

Definition at line 73 of file execMain.c.

Referenced by _PG_init(), and ExecutorEnd().

◆ ExecutorFinish_hook

PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook
extern

Definition at line 72 of file execMain.c.

Referenced by _PG_init(), and ExecutorFinish().

◆ ExecutorRun_hook

PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook
extern

Definition at line 71 of file execMain.c.

Referenced by _PG_init(), and ExecutorRun().

◆ ExecutorStart_hook

PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook
extern

Definition at line 70 of file execMain.c.

Referenced by _PG_init(), and ExecutorStart().