Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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

Go to the source code of this file.

Data Structures

struct  TupOutputState
 

Macros

#define EXEC_FLAG_EXPLAIN_ONLY   0x0001 /* EXPLAIN, no ANALYZE */
 
#define EXEC_FLAG_EXPLAIN_GENERIC   0x0002 /* EXPLAIN (GENERIC_PLAN) */
 
#define EXEC_FLAG_REWIND   0x0004 /* need efficient rescan */
 
#define EXEC_FLAG_BACKWARD   0x0008 /* need backward scan */
 
#define EXEC_FLAG_MARK   0x0010 /* need mark/restore */
 
#define EXEC_FLAG_SKIP_TRIGGERS   0x0020 /* skip AfterTrigger setup */
 
#define EXEC_FLAG_WITH_NO_DATA   0x0040 /* REFRESH ... WITH NO DATA */
 
#define EvalPlanQualSetSlot(epqstate, slot)   ((epqstate)->origslot = (slot))
 
#define do_text_output_oneline(tstate, str_to_emit)
 
#define ResetExprContext(econtext)    MemoryContextReset((econtext)->ecxt_per_tuple_memory)
 
#define GetPerTupleExprContext(estate)
 
#define GetPerTupleMemoryContext(estate)    (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
 
#define ResetPerTupleExprContext(estate)
 

Typedefs

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

Functions

void ExecReScan (PlanState *node)
 
void ExecMarkPos (PlanState *node)
 
void ExecRestrPos (PlanState *node)
 
bool ExecSupportsMarkRestore (Path *pathnode)
 
bool ExecSupportsBackwardScan (Plan *node)
 
bool ExecMaterializesOutput (NodeTag plantype)
 
bool execCurrentOf (CurrentOfExpr *cexpr, ExprContext *econtext, Oid table_oid, ItemPointer current_tid)
 
ExprStateexecTuplesMatchPrepare (TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
 
void execTuplesHashPrepare (int numCols, const Oid *eqOperators, Oid **eqFuncOids, FmgrInfo **hashFunctions)
 
TupleHashTable BuildTupleHashTable (PlanState *parent, TupleDesc inputDesc, const TupleTableSlotOps *inputOps, int numCols, AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, long nbuckets, Size additionalsize, MemoryContext metacxt, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
 
TupleHashEntry LookupTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 *hash)
 
uint32 TupleHashTableHash (TupleHashTable hashtable, TupleTableSlot *slot)
 
TupleHashEntry LookupTupleHashEntryHash (TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 hash)
 
TupleHashEntry FindTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, ExprState *eqcomp, ExprState *hashexpr)
 
void ResetTupleHashTable (TupleHashTable hashtable)
 
static size_t TupleHashEntrySize (void)
 
static MinimalTuple TupleHashEntryGetTuple (TupleHashEntry entry)
 
static void * TupleHashEntryGetAdditional (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)
 
char * ExecBuildSlotValueDescription (Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
 
LockTupleMode ExecUpdateLockMode (EState *estate, ResultRelInfo *relinfo)
 
ExecRowMarkExecFindRowMark (EState *estate, Index rti, bool missing_ok)
 
ExecAuxRowMarkExecBuildAuxRowMark (ExecRowMark *erm, List *targetlist)
 
TupleTableSlotEvalPlanQual (EPQState *epqstate, Relation relation, Index rti, TupleTableSlot *inputslot)
 
void EvalPlanQualInit (EPQState *epqstate, EState *parentestate, Plan *subplan, List *auxrowmarks, int epqParam, List *resultRelations)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
TupleTableSlotEvalPlanQualSlot (EPQState *epqstate, Relation relation, Index rti)
 
bool EvalPlanQualFetchRowMark (EPQState *epqstate, Index rti, TupleTableSlot *slot)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate)
 
void EvalPlanQualEnd (EPQState *epqstate)
 
PlanStateExecInitNode (Plan *node, EState *estate, int eflags)
 
void ExecSetExecProcNode (PlanState *node, ExecProcNodeMtd function)
 
NodeMultiExecProcNode (PlanState *node)
 
void ExecEndNode (PlanState *node)
 
void ExecShutdownNode (PlanState *node)
 
void ExecSetTupleBound (int64 tuples_needed, PlanState *child_node)
 
static TupleTableSlotExecProcNode (PlanState *node)
 
ExprStateExecInitExpr (Expr *node, PlanState *parent)
 
ExprStateExecInitExprWithParams (Expr *node, ParamListInfo ext_params)
 
ExprStateExecInitQual (List *qual, PlanState *parent)
 
ExprStateExecInitCheck (List *qual, PlanState *parent)
 
ListExecInitExprList (List *nodes, PlanState *parent)
 
ExprStateExecBuildAggTrans (AggState *aggstate, struct AggStatePerPhaseData *phase, bool doSort, bool doHash, bool nullcheck)
 
ExprStateExecBuildHash32FromAttrs (TupleDesc desc, const TupleTableSlotOps *ops, FmgrInfo *hashfunctions, Oid *collations, int numCols, AttrNumber *keyColIdx, PlanState *parent, uint32 init_value)
 
ExprStateExecBuildHash32Expr (TupleDesc desc, const TupleTableSlotOps *ops, const Oid *hashfunc_oids, const List *collations, const List *hash_exprs, const bool *opstrict, PlanState *parent, uint32 init_value, bool keep_nulls)
 
ExprStateExecBuildGroupingEqual (TupleDesc ldesc, TupleDesc rdesc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, int numCols, const AttrNumber *keyColIdx, const Oid *eqfunctions, const Oid *collations, PlanState *parent)
 
ExprStateExecBuildParamSetEqual (TupleDesc desc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, const Oid *eqfunctions, const Oid *collations, const List *param_exprs, PlanState *parent)
 
ProjectionInfoExecBuildProjectionInfo (List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
 
ProjectionInfoExecBuildUpdateProjection (List *targetList, bool evalTargetList, List *targetColnos, TupleDesc relDesc, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent)
 
ExprStateExecPrepareExpr (Expr *node, EState *estate)
 
ExprStateExecPrepareQual (List *qual, EState *estate)
 
ExprStateExecPrepareCheck (List *qual, EState *estate)
 
ListExecPrepareExprList (List *nodes, EState *estate)
 
static Datum ExecEvalExpr (ExprState *state, ExprContext *econtext, bool *isNull)
 
static void ExecEvalExprNoReturn (ExprState *state, ExprContext *econtext)
 
static Datum ExecEvalExprSwitchContext (ExprState *state, ExprContext *econtext, bool *isNull)
 
static void ExecEvalExprNoReturnSwitchContext (ExprState *state, ExprContext *econtext)
 
static TupleTableSlotExecProject (ProjectionInfo *projInfo)
 
static bool ExecQual (ExprState *state, ExprContext *econtext)
 
static bool ExecQualAndReset (ExprState *state, ExprContext *econtext)
 
bool ExecCheck (ExprState *state, ExprContext *econtext)
 
SetExprStateExecInitTableFunctionResult (Expr *expr, ExprContext *econtext, PlanState *parent)
 
TuplestorestateExecMakeTableFunctionResult (SetExprState *setexpr, ExprContext *econtext, MemoryContext argContext, TupleDesc expectedDesc, bool randomAccess)
 
SetExprStateExecInitFunctionResultSet (Expr *expr, ExprContext *econtext, PlanState *parent)
 
Datum ExecMakeFunctionResultSet (SetExprState *fcache, ExprContext *econtext, MemoryContext argContext, bool *isNull, ExprDoneCond *isDone)
 
TupleTableSlotExecScan (ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
 
void ExecAssignScanProjectionInfo (ScanState *node)
 
void ExecAssignScanProjectionInfoWithVarno (ScanState *node, int varno)
 
void ExecScanReScan (ScanState *node)
 
void ExecInitResultTypeTL (PlanState *planstate)
 
void ExecInitResultSlot (PlanState *planstate, const TupleTableSlotOps *tts_ops)
 
void ExecInitResultTupleSlotTL (PlanState *planstate, const TupleTableSlotOps *tts_ops)
 
void ExecInitScanTupleSlot (EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
 
TupleTableSlotExecInitExtraTupleSlot (EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
 
TupleTableSlotExecInitNullTupleSlot (EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
 
TupleDesc ExecTypeFromTL (List *targetList)
 
TupleDesc ExecCleanTypeFromTL (List *targetList)
 
TupleDesc ExecTypeFromExprList (List *exprList)
 
void ExecTypeSetColNames (TupleDesc typeInfo, List *namesList)
 
void UpdateChangedParamSet (PlanState *node, Bitmapset *newchg)
 
TupOutputStatebegin_tup_output_tupdesc (DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
 
void do_tup_output (TupOutputState *tstate, const Datum *values, const bool *isnull)
 
void do_text_output_multiline (TupOutputState *tstate, const char *txt)
 
void end_tup_output (TupOutputState *tstate)
 
EStateCreateExecutorState (void)
 
void FreeExecutorState (EState *estate)
 
ExprContextCreateExprContext (EState *estate)
 
ExprContextCreateWorkExprContext (EState *estate)
 
ExprContextCreateStandaloneExprContext (void)
 
void FreeExprContext (ExprContext *econtext, bool isCommit)
 
void ReScanExprContext (ExprContext *econtext)
 
ExprContextMakePerTupleExprContext (EState *estate)
 
void ExecAssignExprContext (EState *estate, PlanState *planstate)
 
TupleDesc ExecGetResultType (PlanState *planstate)
 
const TupleTableSlotOpsExecGetResultSlotOps (PlanState *planstate, bool *isfixed)
 
const TupleTableSlotOpsExecGetCommonSlotOps (PlanState **planstates, int nplans)
 
const TupleTableSlotOpsExecGetCommonChildSlotOps (PlanState *ps)
 
void ExecAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc)
 
void ExecConditionalAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc, int varno)
 
void ExecAssignScanType (ScanState *scanstate, TupleDesc tupDesc)
 
void ExecCreateScanSlotFromOuterPlan (EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
 
bool ExecRelationIsTargetRelation (EState *estate, Index scanrelid)
 
Relation ExecOpenScanRelation (EState *estate, Index scanrelid, int eflags)
 
void ExecInitRangeTable (EState *estate, List *rangeTable, List *permInfos, Bitmapset *unpruned_relids)
 
void ExecCloseRangeTableRelations (EState *estate)
 
void ExecCloseResultRelations (EState *estate)
 
static RangeTblEntryexec_rt_fetch (Index rti, EState *estate)
 
Relation ExecGetRangeTableRelation (EState *estate, Index rti, bool isResultRel)
 
void ExecInitResultRelation (EState *estate, ResultRelInfo *resultRelInfo, Index rti)
 
int executor_errposition (EState *estate, int location)
 
void RegisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
void UnregisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
Datum GetAttributeByName (HeapTupleHeader tuple, const char *attname, bool *isNull)
 
Datum GetAttributeByNum (HeapTupleHeader tuple, AttrNumber attrno, bool *isNull)
 
int ExecTargetListLength (List *targetlist)
 
int ExecCleanTargetListLength (List *targetlist)
 
TupleTableSlotExecGetTriggerOldSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleTableSlotExecGetTriggerNewSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleTableSlotExecGetReturningSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleTableSlotExecGetAllNullSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleConversionMapExecGetChildToRootMap (ResultRelInfo *resultRelInfo)
 
TupleConversionMapExecGetRootToChildMap (ResultRelInfo *resultRelInfo, EState *estate)
 
Oid ExecGetResultRelCheckAsUser (ResultRelInfo *relInfo, EState *estate)
 
BitmapsetExecGetInsertedCols (ResultRelInfo *relinfo, EState *estate)
 
BitmapsetExecGetUpdatedCols (ResultRelInfo *relinfo, EState *estate)
 
BitmapsetExecGetExtraUpdatedCols (ResultRelInfo *relinfo, EState *estate)
 
BitmapsetExecGetAllUpdatedCols (ResultRelInfo *relinfo, EState *estate)
 
void ExecOpenIndices (ResultRelInfo *resultRelInfo, bool speculative)
 
void ExecCloseIndices (ResultRelInfo *resultRelInfo)
 
ListExecInsertIndexTuples (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
 
bool ExecCheckIndexConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, ItemPointer tupleid, List *arbiterIndexes)
 
void check_exclusion_constraint (Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer 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, RepOriginId *delete_origin, TimestampTz *delete_time)
 
bool RelationFindDeletedTupleInfoByIndex (Relation rel, Oid idxoid, TupleTableSlot *searchslot, TransactionId oldestxmin, TransactionId *delete_xid, RepOriginId *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 relkind, const char *nspname, const char *relname)
 
TupleTableSlotExecGetUpdateNewTuple (ResultRelInfo *relinfo, TupleTableSlot *planSlot, TupleTableSlot *oldSlot)
 
ResultRelInfoExecLookupResultRelByOid (ModifyTableState *node, Oid resultoid, bool missing_ok, bool update_cache)
 

Variables

PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook
 
PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook
 
PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook
 
PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook
 
PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
 

Macro Definition Documentation

◆ do_text_output_oneline

#define do_text_output_oneline (   tstate,
  str_to_emit 
)
Value:
do { \
Datum values_[1]; \
bool isnull_[1]; \
values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
isnull_[0] = false; \
do_tup_output(tstate, values_, isnull_); \
pfree(DatumGetPointer(values_[0])); \
} while (0)
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
text * cstring_to_text(const char *s)
Definition: varlena.c:181

Definition at line 625 of file executor.h.

◆ EvalPlanQualSetSlot

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

Definition at line 286 of file executor.h.

◆ EXEC_FLAG_BACKWARD

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

Definition at line 69 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_GENERIC

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

Definition at line 67 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_ONLY

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

Definition at line 66 of file executor.h.

◆ EXEC_FLAG_MARK

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

Definition at line 70 of file executor.h.

◆ EXEC_FLAG_REWIND

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

Definition at line 68 of file executor.h.

◆ EXEC_FLAG_SKIP_TRIGGERS

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

Definition at line 71 of file executor.h.

◆ EXEC_FLAG_WITH_NO_DATA

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

Definition at line 72 of file executor.h.

◆ GetPerTupleExprContext

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

Definition at line 653 of file executor.h.

◆ GetPerTupleMemoryContext

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

Definition at line 658 of file executor.h.

◆ ResetExprContext

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

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 576 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 577 of file executor.h.

◆ ExecutorCheckPerms_hook_type

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

Definition at line 94 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 90 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 86 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 80 of file executor.h.

◆ ExecutorStart_hook_type

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

Definition at line 76 of file executor.h.

◆ Path

typedef struct Path Path

Definition at line 103 of file executor.h.

◆ TupOutputState

Function Documentation

◆ begin_tup_output_tupdesc()

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

Definition at line 2444 of file execTuples.c.

2447{
2448 TupOutputState *tstate;
2449
2450 tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2451
2452 tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2453 tstate->dest = dest;
2454
2455 tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2456
2457 return tstate;
2458}
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1427
void * palloc(Size size)
Definition: mcxt.c:1365
@ CMD_SELECT
Definition: nodes.h:275
TupleTableSlot * slot
Definition: executor.h:609
DestReceiver * dest
Definition: executor.h:610
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121

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

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

◆ BuildTupleHashTable()

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

Definition at line 167 of file execGrouping.c.

181{
182 TupleHashTable hashtable;
183 Size entrysize;
184 Size hash_mem_limit;
185 MemoryContext oldcontext;
186 bool allow_jit;
187 uint32 hash_iv = 0;
188
189 Assert(nbuckets > 0);
190 additionalsize = MAXALIGN(additionalsize);
191 entrysize = sizeof(TupleHashEntryData) + additionalsize;
192
193 /* Limit initial table size request to not more than hash_mem */
194 hash_mem_limit = get_hash_memory_limit() / entrysize;
195 if (nbuckets > hash_mem_limit)
196 nbuckets = hash_mem_limit;
197
198 oldcontext = MemoryContextSwitchTo(metacxt);
199
200 hashtable = (TupleHashTable) palloc(sizeof(TupleHashTableData));
201
202 hashtable->numCols = numCols;
203 hashtable->keyColIdx = keyColIdx;
204 hashtable->tab_collations = collations;
205 hashtable->tablecxt = tablecxt;
206 hashtable->tempcxt = tempcxt;
207 hashtable->additionalsize = additionalsize;
208 hashtable->tableslot = NULL; /* will be made on first lookup */
209 hashtable->inputslot = NULL;
210 hashtable->in_hash_expr = NULL;
211 hashtable->cur_eq_func = NULL;
212
213 /*
214 * If parallelism is in use, even if the leader backend is performing the
215 * scan itself, we don't want to create the hashtable exactly the same way
216 * in all workers. As hashtables are iterated over in keyspace-order,
217 * doing so in all processes in the same way is likely to lead to
218 * "unbalanced" hashtables when the table size initially is
219 * underestimated.
220 */
221 if (use_variable_hash_iv)
223
224 hashtable->hashtab = tuplehash_create(metacxt, nbuckets, hashtable);
225
226 /*
227 * We copy the input tuple descriptor just for safety --- we assume all
228 * input tuples will have equivalent descriptors.
229 */
232
233 /*
234 * If the caller fails to make the metacxt different from the tablecxt,
235 * allowing JIT would lead to the generated functions to a) live longer
236 * than the query or b) be re-generated each time the table is being
237 * reset. Therefore prevent JIT from being used in that case, by not
238 * providing a parent node (which prevents accessing the JitContext in the
239 * EState).
240 */
241 allow_jit = (metacxt != tablecxt);
242
243 /* build hash ExprState for all columns */
244 hashtable->tab_hash_expr = ExecBuildHash32FromAttrs(inputDesc,
245 inputOps,
246 hashfunctions,
247 collations,
248 numCols,
249 keyColIdx,
250 allow_jit ? parent : NULL,
251 hash_iv);
252
253 /* build comparator for all columns */
254 hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
255 inputOps,
257 numCols,
258 keyColIdx, eqfuncoids, collations,
259 allow_jit ? parent : NULL);
260
261 /*
262 * While not pretty, it's ok to not shut down this context, but instead
263 * rely on the containing memory context being reset, as
264 * ExecBuildGroupingEqual() only builds a very simple expression calling
265 * functions (i.e. nothing that'd employ RegisterExprContextCallback()).
266 */
268
269 MemoryContextSwitchTo(oldcontext);
270
271 return hashtable;
272}
int ParallelWorkerNumber
Definition: parallel.c:115
#define MAXALIGN(LEN)
Definition: c.h:811
uint32_t uint32
Definition: c.h:539
size_t Size
Definition: c.h:611
ExprState * ExecBuildHash32FromAttrs(TupleDesc desc, const TupleTableSlotOps *ops, FmgrInfo *hashfunctions, Oid *collations, int numCols, AttrNumber *keyColIdx, PlanState *parent, uint32 init_value)
Definition: execExpr.c:4141
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:4465
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:86
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:357
struct TupleHashTableData * TupleHashTable
Definition: execnodes.h:845
struct TupleHashEntryData TupleHashEntryData
static uint32 murmurhash32(uint32 data)
Definition: hashfn.h:92
Assert(PointerIsAligned(start, uint64))
size_t get_hash_memory_limit(void)
Definition: nodeHash.c:3615
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
AttrNumber * keyColIdx
Definition: execnodes.h:866
tuplehash_hash * hashtab
Definition: execnodes.h:864
ExprState * in_hash_expr
Definition: execnodes.h:876
ExprState * tab_hash_expr
Definition: execnodes.h:867
MemoryContext tempcxt
Definition: execnodes.h:871
ExprState * tab_eq_func
Definition: execnodes.h:868
TupleTableSlot * tableslot
Definition: execnodes.h:873
ExprContext * exprcontext
Definition: execnodes.h:878
MemoryContext tablecxt
Definition: execnodes.h:870
TupleTableSlot * inputslot
Definition: execnodes.h:875
ExprState * cur_eq_func
Definition: execnodes.h:877
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:252

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

Referenced by build_hash_table(), and buildSubPlanHash().

◆ check_exclusion_constraint()

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

Definition at line 956 of file execIndexing.c.

961{
962 (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
963 values, isnull,
964 estate, newIndex,
965 CEOUC_WAIT, false, NULL);
966}
static Datum values[MAXATTR]
Definition: bootstrap.c:153
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool violationOK, ItemPointer conflictTid)
Definition: execIndexing.c:704
@ CEOUC_WAIT
Definition: execIndexing.c:124
Definition: type.h:96

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), and values.

Referenced by IndexCheckExclusion().

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 1010 of file execReplication.c.

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

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

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

◆ CheckSubscriptionRelkind()

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

Definition at line 1120 of file execReplication.c.

1122{
1123 if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
1124 ereport(ERROR,
1125 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1126 errmsg("cannot use relation \"%s.%s\" as logical replication target",
1127 nspname, relname),
1129}
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
NameData relname
Definition: pg_class.h:38

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

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

◆ CheckValidResultRel()

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

Definition at line 1050 of file execMain.c.

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

References generate_unaccent_rules::action, 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, 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  )

Definition at line 88 of file execUtils.c.

89{
90 EState *estate;
91 MemoryContext qcontext;
92 MemoryContext oldcontext;
93
94 /*
95 * Create the per-query context for this Executor run.
96 */
98 "ExecutorState",
100
101 /*
102 * Make the EState node within the per-query context. This way, we don't
103 * need a separate pfree() operation for it at shutdown.
104 */
105 oldcontext = MemoryContextSwitchTo(qcontext);
106
107 estate = makeNode(EState);
108
109 /*
110 * Initialize all fields of the Executor State structure
111 */
113 estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
114 estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
115 estate->es_range_table = NIL;
116 estate->es_range_table_size = 0;
117 estate->es_relations = NULL;
118 estate->es_rowmarks = NULL;
119 estate->es_rteperminfos = NIL;
120 estate->es_plannedstmt = NULL;
121 estate->es_part_prune_infos = NIL;
122
123 estate->es_junkFilter = NULL;
124
125 estate->es_output_cid = (CommandId) 0;
126
127 estate->es_result_relations = NULL;
131
134
135 estate->es_param_list_info = NULL;
136 estate->es_param_exec_vals = NULL;
137
138 estate->es_queryEnv = NULL;
139
140 estate->es_query_cxt = qcontext;
141
142 estate->es_tupleTable = NIL;
143
144 estate->es_processed = 0;
145 estate->es_total_processed = 0;
146
147 estate->es_top_eflags = 0;
148 estate->es_instrument = 0;
149 estate->es_finished = false;
150
151 estate->es_exprcontexts = NIL;
152
153 estate->es_subplanstates = NIL;
154
155 estate->es_auxmodifytables = NIL;
156
157 estate->es_per_tuple_exprcontext = NULL;
158
159 estate->es_sourceText = NULL;
160
161 estate->es_use_parallel_mode = false;
164
165 estate->es_jit_flags = 0;
166 estate->es_jit = NULL;
167
168 /*
169 * Return the executor state structure
170 */
171 MemoryContextSwitchTo(oldcontext);
172
173 return estate;
174}
uint32 CommandId
Definition: c.h:672
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:714
List * es_part_prune_infos
Definition: execnodes.h:670
int es_parallel_workers_to_launch
Definition: execnodes.h:746
List * es_tuple_routing_result_relations
Definition: execnodes.h:698
int es_top_eflags
Definition: execnodes.h:719
struct JitContext * es_jit
Definition: execnodes.h:764
int es_instrument
Definition: execnodes.h:720
PlannedStmt * es_plannedstmt
Definition: execnodes.h:669
QueryEnvironment * es_queryEnv
Definition: execnodes.h:707
ResultRelInfo ** es_result_relations
Definition: execnodes.h:685
ParamExecData * es_param_exec_vals
Definition: execnodes.h:705
uint64 es_total_processed
Definition: execnodes.h:716
List * es_range_table
Definition: execnodes.h:662
List * es_rteperminfos
Definition: execnodes.h:668
List * es_exprcontexts
Definition: execnodes.h:723
ParamListInfo es_param_list_info
Definition: execnodes.h:704
ExecRowMark ** es_rowmarks
Definition: execnodes.h:666
bool es_finished
Definition: execnodes.h:721
List * es_insert_pending_result_relations
Definition: execnodes.h:771
MemoryContext es_query_cxt
Definition: execnodes.h:710
List * es_tupleTable
Definition: execnodes.h:712
ScanDirection es_direction
Definition: execnodes.h:659
List * es_trig_target_relations
Definition: execnodes.h:701
int es_jit_flags
Definition: execnodes.h:763
List * es_opened_result_relations
Definition: execnodes.h:688
bool es_use_parallel_mode
Definition: execnodes.h:744
Relation * es_relations
Definition: execnodes.h:664
List * es_subplanstates
Definition: execnodes.h:725
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:734
int es_parallel_workers_launched
Definition: execnodes.h:748
CommandId es_output_cid
Definition: execnodes.h:682
Index es_range_table_size
Definition: execnodes.h:663
List * es_insert_pending_modifytables
Definition: execnodes.h:772
const char * es_sourceText
Definition: execnodes.h:677
Snapshot es_snapshot
Definition: execnodes.h:660
List * es_auxmodifytables
Definition: execnodes.h:727
JunkFilter * es_junkFilter
Definition: execnodes.h:679
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:661

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, EState::es_auxmodifytables, EState::es_crosscheck_snapshot, EState::es_direction, EState::es_exprcontexts, EState::es_finished, EState::es_insert_pending_modifytables, EState::es_insert_pending_result_relations, EState::es_instrument, EState::es_jit, EState::es_jit_flags, EState::es_junkFilter, EState::es_opened_result_relations, EState::es_output_cid, EState::es_parallel_workers_launched, EState::es_parallel_workers_to_launch, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_part_prune_infos, EState::es_per_tuple_exprcontext, EState::es_plannedstmt, EState::es_processed, EState::es_query_cxt, EState::es_queryEnv, EState::es_range_table, EState::es_range_table_size, EState::es_relations, EState::es_result_relations, EState::es_rowmarks, EState::es_rteperminfos, EState::es_snapshot, EState::es_sourceText, EState::es_subplanstates, EState::es_top_eflags, EState::es_total_processed, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, EState::es_tupleTable, EState::es_use_parallel_mode, 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(), operator_predicate_proof(), plpgsql_create_econtext(), plpgsql_inline_handler(), standard_ExecutorStart(), tuplesort_begin_cluster(), and validateDomainCheckConstraint().

◆ CreateExprContext()

ExprContext * CreateExprContext ( EState estate)

Definition at line 307 of file execUtils.c.

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

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext * CreateStandaloneExprContext ( void  )

Definition at line 357 of file execUtils.c.

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

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

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

◆ CreateWorkExprContext()

ExprContext * CreateWorkExprContext ( EState estate)

Definition at line 322 of file execUtils.c.

323{
324 Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
325
326 maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
327
328 /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
329 maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
330
331 /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
332 maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
333
335 ALLOCSET_DEFAULT_INITSIZE, maxBlockSize);
336}
#define Min(x, y)
Definition: c.h:1004
#define Max(x, y)
Definition: c.h:998
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
Definition: pg_bitutils.h:442

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 
)

Definition at line 2492 of file execTuples.c.

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

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

Referenced by ExplainQuery().

◆ do_tup_output()

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

Definition at line 2464 of file execTuples.c.

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

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

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

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 2522 of file execTuples.c.

2523{
2524 tstate->dest->rShutdown(tstate->dest);
2525 /* note that destroying the dest is not ours to do */
2527 pfree(tstate);
2528}
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1443
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124

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

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

◆ EvalPlanQual()

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

Definition at line 2639 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2922 of file execMain.c.

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

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

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 3169 of file execMain.c.

3170{
3171 EState *estate = epqstate->recheckestate;
3172 Index rtsize;
3173 MemoryContext oldcontext;
3174 ListCell *l;
3175
3176 rtsize = epqstate->parentestate->es_range_table_size;
3177
3178 /*
3179 * We may have a tuple table, even if EPQ wasn't started, because we allow
3180 * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
3181 */
3182 if (epqstate->tuple_table != NIL)
3183 {
3184 memset(epqstate->relsubs_slot, 0,
3185 rtsize * sizeof(TupleTableSlot *));
3186 ExecResetTupleTable(epqstate->tuple_table, true);
3187 epqstate->tuple_table = NIL;
3188 }
3189
3190 /* EPQ wasn't started, nothing further to do */
3191 if (estate == NULL)
3192 return;
3193
3194 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3195
3196 ExecEndNode(epqstate->recheckplanstate);
3197
3198 foreach(l, estate->es_subplanstates)
3199 {
3200 PlanState *subplanstate = (PlanState *) lfirst(l);
3201
3202 ExecEndNode(subplanstate);
3203 }
3204
3205 /* throw away the per-estate tuple table, some node may have used it */
3206 ExecResetTupleTable(estate->es_tupleTable, false);
3207
3208 /* Close any result and trigger target relations attached to this EState */
3210
3211 MemoryContextSwitchTo(oldcontext);
3212
3213 FreeExecutorState(estate);
3214
3215 /* Mark EPQState idle */
3216 epqstate->origslot = NULL;
3217 epqstate->recheckestate = NULL;
3218 epqstate->recheckplanstate = NULL;
3219 epqstate->relsubs_rowmark = NULL;
3220 epqstate->relsubs_done = NULL;
3221 epqstate->relsubs_blocked = NULL;
3222}
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1565
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1380
void FreeExecutorState(EState *estate)
Definition: execUtils.c:192
#define lfirst(lc)
Definition: pg_list.h:172
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1334
TupleTableSlot * origslot
Definition: execnodes.h:1322
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1306
List * tuple_table
Definition: execnodes.h:1305

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

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

◆ EvalPlanQualFetchRowMark()

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

Definition at line 2795 of file execMain.c.

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

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

Referenced by ExecScanFetch().

◆ EvalPlanQualInit()

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

Definition at line 2708 of file execMain.c.

2711{
2712 Index rtsize = parentestate->es_range_table_size;
2713
2714 /* initialize data not changing over EPQState's lifetime */
2715 epqstate->parentestate = parentestate;
2716 epqstate->epqParam = epqParam;
2717 epqstate->resultRelations = resultRelations;
2718
2719 /*
2720 * Allocate space to reference a slot for each potential rti - do so now
2721 * rather than in EvalPlanQualBegin(), as done for other dynamically
2722 * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2723 * that *may* need EPQ later, without forcing the overhead of
2724 * EvalPlanQualBegin().
2725 */
2726 epqstate->tuple_table = NIL;
2727 epqstate->relsubs_slot = (TupleTableSlot **)
2728 palloc0(rtsize * sizeof(TupleTableSlot *));
2729
2730 /* ... and remember data that EvalPlanQualBegin will need */
2731 epqstate->plan = subplan;
2732 epqstate->arowMarks = auxrowmarks;
2733
2734 /* ... and mark the EPQ state inactive */
2735 epqstate->origslot = NULL;
2736 epqstate->recheckestate = NULL;
2737 epqstate->recheckplanstate = NULL;
2738 epqstate->relsubs_rowmark = NULL;
2739 epqstate->relsubs_done = NULL;
2740 epqstate->relsubs_blocked = NULL;
2741}
void * palloc0(Size size)
Definition: mcxt.c:1395
List * resultRelations
Definition: execnodes.h:1297
List * arowMarks
Definition: execnodes.h:1314

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

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

◆ EvalPlanQualNext()

TupleTableSlot * EvalPlanQualNext ( EPQState epqstate)

Definition at line 2906 of file execMain.c.

2907{
2908 MemoryContext oldcontext;
2909 TupleTableSlot *slot;
2910
2911 oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2912 slot = ExecProcNode(epqstate->recheckplanstate);
2913 MemoryContextSwitchTo(oldcontext);
2914
2915 return slot;
2916}
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:311

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

Referenced by EvalPlanQual(), and ExecLockRows().

◆ EvalPlanQualSetPlan()

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

Definition at line 2750 of file execMain.c.

2751{
2752 /* If we have a live EPQ query, shut it down */
2753 EvalPlanQualEnd(epqstate);
2754 /* And set/change the plan pointer */
2755 epqstate->plan = subplan;
2756 /* The rowmarks depend on the plan, too */
2757 epqstate->arowMarks = auxrowmarks;
2758}
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3169

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2767 of file execMain.c.

2769{
2770 TupleTableSlot **slot;
2771
2772 Assert(relation);
2773 Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2774 slot = &epqstate->relsubs_slot[rti - 1];
2775
2776 if (*slot == NULL)
2777 {
2778 MemoryContext oldcontext;
2779
2780 oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2781 *slot = table_slot_create(relation, &epqstate->tuple_table);
2782 MemoryContextSwitchTo(oldcontext);
2783 }
2784
2785 return *slot;
2786}
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:92

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

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

◆ exec_rt_fetch()

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

Definition at line 583 of file execUtils.c.

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

References ExecBuildProjectionInfo(), PlanState::plan, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::ps_ResultTupleSlot, and Plan::targetlist.

Referenced by ExecConditionalAssignProjectionInfo(), ExecInitAgg(), ExecInitGroup(), ExecInitHashJoin(), ExecInitMergeJoin(), ExecInitNestLoop(), ExecInitResult(), and ExecInitWindowAgg().

◆ ExecAssignScanProjectionInfo()

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 692 of file execUtils.c.

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

References ExecSetSlotDescriptor(), and ScanState::ss_ScanTupleSlot.

Referenced by ExecWorkTableScan().

◆ ExecBuildAggTrans()

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

◆ ExecBuildAuxRowMark()

ExecAuxRowMark * ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2569 of file execMain.c.

2570{
2572 char resname[32];
2573
2574 aerm->rowmark = erm;
2575
2576 /* Look up the resjunk columns associated with this rowmark */
2577 if (erm->markType != ROW_MARK_COPY)
2578 {
2579 /* need ctid for all methods other than COPY */
2580 snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2581 aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2582 resname);
2584 elog(ERROR, "could not find junk %s column", resname);
2585 }
2586 else
2587 {
2588 /* need wholerow if COPY */
2589 snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2590 aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2591 resname);
2593 elog(ERROR, "could not find junk %s column", resname);
2594 }
2595
2596 /* if child rel, need tableoid */
2597 if (erm->rti != erm->prti)
2598 {
2599 snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2600 aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2601 resname);
2603 elog(ERROR, "could not find junk %s column", resname);
2604 }
2605
2606 return aerm;
2607}
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:222
#define snprintf
Definition: port.h:239
Index rowmarkId
Definition: execnodes.h:801

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecBuildGroupingEqual()

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

Definition at line 4465 of file execExpr.c.

4472{
4474 ExprEvalStep scratch = {0};
4475 int maxatt = -1;
4476 List *adjust_jumps = NIL;
4477 ListCell *lc;
4478
4479 /*
4480 * When no columns are actually compared, the result's always true. See
4481 * special case in ExecQual().
4482 */
4483 if (numCols == 0)
4484 return NULL;
4485
4486 state->expr = NULL;
4487 state->flags = EEO_FLAG_IS_QUAL;
4488 state->parent = parent;
4489
4490 scratch.resvalue = &state->resvalue;
4491 scratch.resnull = &state->resnull;
4492
4493 /* compute max needed attribute */
4494 for (int natt = 0; natt < numCols; natt++)
4495 {
4496 int attno = keyColIdx[natt];
4497
4498 if (attno > maxatt)
4499 maxatt = attno;
4500 }
4501 Assert(maxatt >= 0);
4502
4503 /* push deform steps */
4504 scratch.opcode = EEOP_INNER_FETCHSOME;
4505 scratch.d.fetch.last_var = maxatt;
4506 scratch.d.fetch.fixed = false;
4507 scratch.d.fetch.known_desc = ldesc;
4508 scratch.d.fetch.kind = lops;
4509 if (ExecComputeSlotInfo(state, &scratch))
4510 ExprEvalPushStep(state, &scratch);
4511
4512 scratch.opcode = EEOP_OUTER_FETCHSOME;
4513 scratch.d.fetch.last_var = maxatt;
4514 scratch.d.fetch.fixed = false;
4515 scratch.d.fetch.known_desc = rdesc;
4516 scratch.d.fetch.kind = rops;
4517 if (ExecComputeSlotInfo(state, &scratch))
4518 ExprEvalPushStep(state, &scratch);
4519
4520 /*
4521 * Start comparing at the last field (least significant sort key). That's
4522 * the most likely to be different if we are dealing with sorted input.
4523 */
4524 for (int natt = numCols; --natt >= 0;)
4525 {
4526 int attno = keyColIdx[natt];
4527 Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
4528 Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
4529 Oid foid = eqfunctions[natt];
4530 Oid collid = collations[natt];
4531 FmgrInfo *finfo;
4532 FunctionCallInfo fcinfo;
4533 AclResult aclresult;
4534
4535 /* Check permission to call function */
4536 aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4537 if (aclresult != ACLCHECK_OK)
4538 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4539
4541
4542 /* Set up the primary fmgr lookup information */
4543 finfo = palloc0(sizeof(FmgrInfo));
4544 fcinfo = palloc0(SizeForFunctionCallInfo(2));
4545 fmgr_info(foid, finfo);
4546 fmgr_info_set_expr(NULL, finfo);
4547 InitFunctionCallInfoData(*fcinfo, finfo, 2,
4548 collid, NULL, NULL);
4549
4550 /* left arg */
4551 scratch.opcode = EEOP_INNER_VAR;
4552 scratch.d.var.attnum = attno - 1;
4553 scratch.d.var.vartype = latt->atttypid;
4555 scratch.resvalue = &fcinfo->args[0].value;
4556 scratch.resnull = &fcinfo->args[0].isnull;
4557 ExprEvalPushStep(state, &scratch);
4558
4559 /* right arg */
4560 scratch.opcode = EEOP_OUTER_VAR;
4561 scratch.d.var.attnum = attno - 1;
4562 scratch.d.var.vartype = ratt->atttypid;
4564 scratch.resvalue = &fcinfo->args[1].value;
4565 scratch.resnull = &fcinfo->args[1].isnull;
4566 ExprEvalPushStep(state, &scratch);
4567
4568 /* evaluate distinctness */
4569 scratch.opcode = EEOP_NOT_DISTINCT;
4570 scratch.d.func.finfo = finfo;
4571 scratch.d.func.fcinfo_data = fcinfo;
4572 scratch.d.func.fn_addr = finfo->fn_addr;
4573 scratch.d.func.nargs = 2;
4574 scratch.resvalue = &state->resvalue;
4575 scratch.resnull = &state->resnull;
4576 ExprEvalPushStep(state, &scratch);
4577
4578 /* then emit EEOP_QUAL to detect if result is false (or null) */
4579 scratch.opcode = EEOP_QUAL;
4580 scratch.d.qualexpr.jumpdone = -1;
4581 scratch.resvalue = &state->resvalue;
4582 scratch.resnull = &state->resnull;
4583 ExprEvalPushStep(state, &scratch);
4584 adjust_jumps = lappend_int(adjust_jumps,
4585 state->steps_len - 1);
4586 }
4587
4588 /* adjust jump targets */
4589 foreach(lc, adjust_jumps)
4590 {
4591 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4592
4593 Assert(as->opcode == EEOP_QUAL);
4594 Assert(as->d.qualexpr.jumpdone == -1);
4595 as->d.qualexpr.jumpdone = state->steps_len;
4596 }
4597
4598 scratch.resvalue = NULL;
4599 scratch.resnull = NULL;
4600 scratch.opcode = EEOP_DONE_RETURN;
4601 ExprEvalPushStep(state, &scratch);
4602
4604
4605 return state;
4606}
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2652
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3834
Oid collid
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2678
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:3062
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:902
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:190
@ EEOP_DONE_RETURN
Definition: execExpr.h:69
@ EEOP_INNER_VAR
Definition: execExpr.h:82
@ EEOP_QUAL
Definition: execExpr.h:148
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:75
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:76
@ EEOP_OUTER_VAR
Definition: execExpr.h:83
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:74
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
List * lappend_int(List *list, int datum)
Definition: list.c:357
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1775
Oid GetUserId(void)
Definition: miscinit.c:469
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
@ OBJECT_FUNCTION
Definition: parsenodes.h:2343
#define ACL_EXECUTE
Definition: parsenodes.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
#define lfirst_int(lc)
Definition: pg_list.h:173
@ VAR_RETURNING_DEFAULT
Definition: primnodes.h:256
union ExprEvalStep::@56 d
int last_var
Definition: execExpr.h:325
struct ExprEvalStep::@56::@57 fetch
VarReturningType varreturningtype
Definition: execExpr.h:341
struct ExprEvalStep::@56::@58 var
intptr_t opcode
Definition: execExpr.h:307
struct ExprEvalStep::@56::@64 func
PGFunction fn_addr
Definition: execExpr.h:391
TupleDesc known_desc
Definition: execExpr.h:329
Datum * resvalue
Definition: execExpr.h:310
const TupleTableSlotOps * kind
Definition: execExpr.h:331
FunctionCallInfo fcinfo_data
Definition: execExpr.h:389
int jumpdone
Definition: execExpr.h:374
bool fixed
Definition: execExpr.h:327
bool * resnull
Definition: execExpr.h:311
FmgrInfo * finfo
Definition: execExpr.h:388
struct ExprEvalStep::@56::@66 qualexpr
Definition: fmgr.h:57
PGFunction fn_addr
Definition: fmgr.h:58
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Definition: pg_list.h:54
Datum value
Definition: postgres.h:87
bool isnull
Definition: postgres.h:89
Definition: regguts.h:323
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert(), ExprEvalStep::attnum, collid, ExprEvalStep::d, 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(), ExprEvalStep::fcinfo_data, ExprEvalStep::fetch, ExprEvalStep::finfo, ExprEvalStep::fixed, fmgr_info(), fmgr_info_set_expr, ExprEvalStep::fn_addr, FmgrInfo::fn_addr, ExprEvalStep::func, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvokeFunctionExecuteHook, NullableDatum::isnull, ExprEvalStep::jumpdone, ExprEvalStep::kind, ExprEvalStep::known_desc, lappend_int(), ExprEvalStep::last_var, lfirst_int, makeNode, ExprEvalStep::nargs, NIL, object_aclcheck(), OBJECT_FUNCTION, ExprEvalStep::opcode, palloc0(), ExprEvalStep::qualexpr, ExprEvalStep::resnull, ExprEvalStep::resvalue, SizeForFunctionCallInfo, TupleDescAttr(), NullableDatum::value, ExprEvalStep::var, VAR_RETURNING_DEFAULT, ExprEvalStep::varreturningtype, and ExprEvalStep::vartype.

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

◆ ExecBuildHash32Expr()

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

Definition at line 4300 of file execExpr.c.

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

References FunctionCallInfoBaseData::args, Assert(), ExprEvalStep::d, 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(), ExprEvalStep::fcinfo_data, ExprEvalStep::finfo, fmgr_info(), ExprEvalStep::fn_addr, FmgrInfo::fn_addr, forboth, foreach_current_index, ExprEvalStep::hashdatum, ExprEvalStep::hashdatum_initvalue, i, ExprEvalStep::init_value, InitFunctionCallInfoData, ExprEvalStep::iresult, NullableDatum::isnull, ExprEvalStep::jumpdone, lappend_int(), lfirst, lfirst_int, lfirst_oid, list_length(), makeNode, NIL, ExprEvalStep::opcode, palloc(), palloc0(), ExprEvalStep::resnull, ExprEvalStep::resvalue, 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 
)

Definition at line 4141 of file execExpr.c.

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

References FunctionCallInfoBaseData::args, Assert(), attnum, ExprEvalStep::attnum, ExprEvalStep::d, EEOP_DONE_RETURN, EEOP_HASHDATUM_FIRST, EEOP_HASHDATUM_NEXT32, EEOP_HASHDATUM_SET_INITVAL, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, ExecComputeSlotInfo(), ExecReadyExpr(), ExprEvalPushStep(), ExprEvalStep::fcinfo_data, ExprEvalStep::fetch, ExprEvalStep::finfo, ExprEvalStep::fixed, ExprEvalStep::fn_addr, FmgrInfo::fn_addr, ExprEvalStep::hashdatum, ExprEvalStep::hashdatum_initvalue, i, ExprEvalStep::init_value, InitFunctionCallInfoData, ExprEvalStep::iresult, NullableDatum::isnull, ExprEvalStep::jumpdone, ExprEvalStep::kind, ExprEvalStep::known_desc, ExprEvalStep::last_var, makeNode, Max, ExprEvalStep::opcode, palloc(), palloc0(), ExprEvalStep::resnull, ExprEvalStep::resvalue, SizeForFunctionCallInfo, TupleDescAttr(), UInt32GetDatum(), NullableDatum::value, ExprEvalStep::var, VAR_RETURNING_DEFAULT, ExprEvalStep::varreturningtype, and ExprEvalStep::vartype.

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 
)

Definition at line 4624 of file execExpr.c.

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

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert(), ExprEvalStep::attnum, collid, ExprEvalStep::d, 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(), ExprEvalStep::fcinfo_data, ExprEvalStep::fetch, ExprEvalStep::finfo, ExprEvalStep::fixed, fmgr_info(), fmgr_info_set_expr, ExprEvalStep::fn_addr, FmgrInfo::fn_addr, ExprEvalStep::func, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvokeFunctionExecuteHook, NullableDatum::isnull, ExprEvalStep::jumpdone, ExprEvalStep::kind, ExprEvalStep::known_desc, lappend_int(), ExprEvalStep::last_var, lfirst_int, list_length(), makeNode, ExprEvalStep::nargs, NIL, object_aclcheck(), OBJECT_FUNCTION, ExprEvalStep::opcode, palloc0(), ExprEvalStep::qualexpr, ExprEvalStep::resnull, ExprEvalStep::resvalue, SizeForFunctionCallInfo, TupleDescAttr(), NullableDatum::value, ExprEvalStep::var, VAR_RETURNING_DEFAULT, ExprEvalStep::varreturningtype, and ExprEvalStep::vartype.

Referenced by ExecInitMemoize().

◆ ExecBuildProjectionInfo()

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

Definition at line 370 of file execExpr.c.

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

References ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, attnum, ExprEvalStep::attnum, ExprEvalStep::d, 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(), TargetEntry::expr, ExprEvalPushStep(), exprType(), get_typlen(), if(), INNER_VAR, IsA, lfirst_node, makeNode, ExprEvalStep::opcode, OUTER_VAR, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TargetEntry::resno, ExprEvalStep::resultnum, TupleDescAttr(), ExprState::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 
)

Definition at line 2381 of file execMain.c.

2386{
2388 StringInfoData collist;
2389 bool write_comma = false;
2390 bool write_comma_collist = false;
2391 int i;
2392 AclResult aclresult;
2393 bool table_perm = false;
2394 bool any_perm = false;
2395
2396 /*
2397 * Check if RLS is enabled and should be active for the relation; if so,
2398 * then don't return anything. Otherwise, go through normal permission
2399 * checks.
2400 */
2401 if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2402 return NULL;
2403
2405
2407
2408 /*
2409 * Check if the user has permissions to see the row. Table-level SELECT
2410 * allows access to all columns. If the user does not have table-level
2411 * SELECT then we check each column and include those the user has SELECT
2412 * rights on. Additionally, we always include columns the user provided
2413 * data for.
2414 */
2415 aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2416 if (aclresult != ACLCHECK_OK)
2417 {
2418 /* Set up the buffer for the column list */
2419 initStringInfo(&collist);
2420 appendStringInfoChar(&collist, '(');
2421 }
2422 else
2423 table_perm = any_perm = true;
2424
2425 /* Make sure the tuple is fully deconstructed */
2426 slot_getallattrs(slot);
2427
2428 for (i = 0; i < tupdesc->natts; i++)
2429 {
2430 bool column_perm = false;
2431 char *val;
2432 int vallen;
2433 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2434
2435 /* ignore dropped columns */
2436 if (att->attisdropped)
2437 continue;
2438
2439 if (!table_perm)
2440 {
2441 /*
2442 * No table-level SELECT, so need to make sure they either have
2443 * SELECT rights on the column or that they have provided the data
2444 * for the column. If not, omit this column from the error
2445 * message.
2446 */
2447 aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2450 modifiedCols) || aclresult == ACLCHECK_OK)
2451 {
2452 column_perm = any_perm = true;
2453
2454 if (write_comma_collist)
2455 appendStringInfoString(&collist, ", ");
2456 else
2457 write_comma_collist = true;
2458
2459 appendStringInfoString(&collist, NameStr(att->attname));
2460 }
2461 }
2462
2463 if (table_perm || column_perm)
2464 {
2465 if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
2466 val = "virtual";
2467 else if (slot->tts_isnull[i])
2468 val = "null";
2469 else
2470 {
2471 Oid foutoid;
2472 bool typisvarlena;
2473
2474 getTypeOutputInfo(att->atttypid,
2475 &foutoid, &typisvarlena);
2476 val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2477 }
2478
2479 if (write_comma)
2481 else
2482 write_comma = true;
2483
2484 /* truncate if needed */
2485 vallen = strlen(val);
2486 if (vallen <= maxfieldlen)
2487 appendBinaryStringInfo(&buf, val, vallen);
2488 else
2489 {
2490 vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2491 appendBinaryStringInfo(&buf, val, vallen);
2492 appendStringInfoString(&buf, "...");
2493 }
2494 }
2495 }
2496
2497 /* If we end up with zero columns being returned, then return NULL. */
2498 if (!any_perm)
2499 return NULL;
2500
2502
2503 if (!table_perm)
2504 {
2505 appendStringInfoString(&collist, ") = ");
2506 appendBinaryStringInfo(&collist, buf.data, buf.len);
2507
2508 return collist.data;
2509 }
2510
2511 return buf.data;
2512}
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:3866
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4037
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
#define NameStr(name)
Definition: c.h:752
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1762
long val
Definition: informix.c:689
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:3074
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1084
#define ACL_SELECT
Definition: parsenodes.h:77
static char * buf
Definition: pg_test_fsync.c:72
#define InvalidOid
Definition: postgres_ext.h:37
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:372

References ACL_SELECT, ACLCHECK_OK, appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), bms_is_member(), buf, check_enable_rls(), StringInfoData::data, 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 build_tuple_value_details(), ExecConstraints(), ExecPartitionCheckEmitError(), ExecWithCheckOptions(), and ReportNotNullViolationError().

◆ ExecBuildUpdateProjection()

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

Definition at line 547 of file execExpr.c.

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

References Assert(), ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, CompactAttribute::attisdropped, attnum, ExprEvalStep::attnum, bms_add_member(), bms_is_member(), ExprEvalStep::constval, ExprEvalStep::d, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_CONST, EEOP_DONE_NO_RETURN, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecInitExprRec(), ExecPushExprSetupSteps(), ExecReadyExpr(), TargetEntry::expr, expr_setup_walker(), ExprEvalPushStep(), exprType(), forboth, format_type_be(), ExprEvalStep::isnull, ExprSetupInfo::last_outer, ExprSetupInfo::last_scan, lfirst_int, lfirst_node, list_length(), makeNode, TupleDescData::natts, NIL, ExprEvalStep::opcode, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, ExprEvalStep::resnull, ExprEvalStep::resultnum, ExprEvalStep::resvalue, TupleDescAttr(), TupleDescCompactAttr(), ExprState::type, and ExprEvalStep::value.

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)

Definition at line 872 of file execExpr.c.

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

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

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

◆ ExecCheckIndexConstraints()

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

Definition at line 542 of file execIndexing.c.

545{
546 int i;
547 int numIndices;
548 RelationPtr relationDescs;
549 Relation heapRelation;
550 IndexInfo **indexInfoArray;
551 ExprContext *econtext;
553 bool isnull[INDEX_MAX_KEYS];
554 ItemPointerData invalidItemPtr;
555 bool checkedIndex = false;
556
557 ItemPointerSetInvalid(conflictTid);
558 ItemPointerSetInvalid(&invalidItemPtr);
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;
585 bool satisfiesConstraint;
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)
607 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
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 {
617 ExprState *predicate;
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
645 satisfiesConstraint =
646 check_exclusion_or_unique_constraint(heapRelation, indexRelation,
647 indexInfo, tupleid,
648 values, isnull, estate, false,
649 CEOUC_WAIT, true,
650 conflictTid);
651 if (!satisfiesConstraint)
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:793
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:516
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:2730
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:6103
bool ii_Unique
Definition: execnodes.h:200
ExprState * ii_PredicateState
Definition: execnodes.h:185
Oid * ii_ExclusionOps
Definition: execnodes.h:188
bool ii_ReadyForInserts
Definition: execnodes.h:204
List * ii_Predicate
Definition: execnodes.h:183
Form_pg_index rd_index
Definition: rel.h:192
int ri_NumIndices
Definition: execnodes.h:483
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:486
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:489

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

Referenced by ExecInsert(), and FindConflictTuple().

◆ ExecCheckOneRelPerms()

bool ExecCheckOneRelPerms ( RTEPermissionInfo perminfo)

Definition at line 646 of file execMain.c.

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

References ACL_INSERT, ACL_SELECT, ACL_UPDATE, ACLCHECK_OK, ACLMASK_ALL, ACLMASK_ANY, Assert(), bms_is_empty, bms_next_member(), RTEPermissionInfo::checkAsUser, ExecCheckPermissionsModified(), FirstLowInvalidHeapAttributeNumber, GetUserId(), RTEPermissionInfo::insertedCols, InvalidAttrNumber, OidIsValid, pg_attribute_aclcheck(), pg_attribute_aclcheck_all(), pg_class_aclmask(), RTEPermissionInfo::relid, RTEPermissionInfo::requiredPerms, RTEPermissionInfo::selectedCols, and RTEPermissionInfo::updatedCols.

Referenced by ExecCheckPermissions(), and subquery_planner().

◆ ExecCheckPermissions()

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

Definition at line 582 of file execMain.c.

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

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

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1185 of file execUtils.c.

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

References len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 2139 of file execTuples.c.

2140{
2141 return ExecTypeFromTLInternal(targetList, true);
2142}
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
Definition: execTuples.c:2145

References ExecTypeFromTLInternal().

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 238 of file execIndexing.c.

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

Definition at line 1625 of file execMain.c.

1626{
1627 int i;
1628
1629 for (i = 0; i < estate->es_range_table_size; i++)
1630 {
1631 if (estate->es_relations[i])
1632 table_close(estate->es_relations[i], NoLock);
1633 }
1634}
#define NoLock
Definition: lockdefs.h:34
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126

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

Referenced by CopyFrom(), and ExecEndPlan().

◆ ExecCloseResultRelations()

void ExecCloseResultRelations ( EState estate)

Definition at line 1565 of file execMain.c.

1566{
1567 ListCell *l;
1568
1569 /*
1570 * close indexes of result relation(s) if any. (Rels themselves are
1571 * closed in ExecCloseRangeTableRelations())
1572 *
1573 * In addition, close the stub RTs that may be in each resultrel's
1574 * ri_ancestorResultRels.
1575 */
1576 foreach(l, estate->es_opened_result_relations)
1577 {
1578 ResultRelInfo *resultRelInfo = lfirst(l);
1579 ListCell *lc;
1580
1581 ExecCloseIndices(resultRelInfo);
1582 foreach(lc, resultRelInfo->ri_ancestorResultRels)
1583 {
1584 ResultRelInfo *rInfo = lfirst(lc);
1585
1586 /*
1587 * Ancestors with RTI > 0 (should only be the root ancestor) are
1588 * closed by ExecCloseRangeTableRelations.
1589 */
1590 if (rInfo->ri_RangeTableIndex > 0)
1591 continue;
1592
1594 }
1595 }
1596
1597 /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
1598 foreach(l, estate->es_trig_target_relations)
1599 {
1600 ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1601
1602 /*
1603 * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
1604 * might be issuing a duplicate close against a Relation opened by
1605 * ExecGetRangeTableRelation.
1606 */
1607 Assert(resultRelInfo->ri_RangeTableIndex == 0);
1608
1609 /*
1610 * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
1611 * these rels, we needn't call ExecCloseIndices either.
1612 */
1613 Assert(resultRelInfo->ri_NumIndices == 0);
1614
1615 table_close(resultRelInfo->ri_RelationDesc, NoLock);
1616 }
1617}
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:238
Index ri_RangeTableIndex
Definition: execnodes.h:477
List * ri_ancestorResultRels
Definition: execnodes.h:628

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

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

◆ ExecConditionalAssignProjectionInfo()

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

Definition at line 603 of file execUtils.c.

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

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

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

◆ ExecConstraints()

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

Definition at line 1970 of file execMain.c.

1972{
1973 Relation rel = resultRelInfo->ri_RelationDesc;
1974 TupleDesc tupdesc = RelationGetDescr(rel);
1975 TupleConstr *constr = tupdesc->constr;
1976 Bitmapset *modifiedCols;
1977 List *notnull_virtual_attrs = NIL;
1978
1979 Assert(constr); /* we should not be called otherwise */
1980
1981 /*
1982 * Verify not-null constraints.
1983 *
1984 * Not-null constraints on virtual generated columns are collected and
1985 * checked separately below.
1986 */
1987 if (constr->has_not_null)
1988 {
1989 for (AttrNumber attnum = 1; attnum <= tupdesc->natts; attnum++)
1990 {
1991 Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
1992
1993 if (att->attnotnull && att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
1994 notnull_virtual_attrs = lappend_int(notnull_virtual_attrs, attnum);
1995 else if (att->attnotnull && slot_attisnull(slot, attnum))
1996 ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
1997 }
1998 }
1999
2000 /*
2001 * Verify not-null constraints on virtual generated column, if any.
2002 */
2003 if (notnull_virtual_attrs)
2004 {
2006
2007 attnum = ExecRelGenVirtualNotNull(resultRelInfo, slot, estate,
2008 notnull_virtual_attrs);
2010 ReportNotNullViolationError(resultRelInfo, slot, estate, attnum);
2011 }
2012
2013 /*
2014 * Verify check constraints.
2015 */
2016 if (rel->rd_rel->relchecks > 0)
2017 {
2018 const char *failed;
2019
2020 if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2021 {
2022 char *val_desc;
2023 Relation orig_rel = rel;
2024
2025 /*
2026 * If the tuple has been routed, it's been converted to the
2027 * partition's rowtype, which might differ from the root table's.
2028 * We must convert it back to the root table's rowtype so that
2029 * val_desc shown error message matches the input tuple.
2030 */
2031 if (resultRelInfo->ri_RootResultRelInfo)
2032 {
2033 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
2034 TupleDesc old_tupdesc = RelationGetDescr(rel);
2035 AttrMap *map;
2036
2037 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
2038 /* a reverse map */
2039 map = build_attrmap_by_name_if_req(old_tupdesc,
2040 tupdesc,
2041 false);
2042
2043 /*
2044 * Partition-specific slot's tupdesc can't be changed, so
2045 * allocate a new one.
2046 */
2047 if (map != NULL)
2048 slot = execute_attr_map_slot(map, slot,
2050 modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
2051 ExecGetUpdatedCols(rootrel, estate));
2052 rel = rootrel->ri_RelationDesc;
2053 }
2054 else
2055 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
2056 ExecGetUpdatedCols(resultRelInfo, estate));
2058 slot,
2059 tupdesc,
2060 modifiedCols,
2061 64);
2062 ereport(ERROR,
2063 (errcode(ERRCODE_CHECK_VIOLATION),
2064 errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2065 RelationGetRelationName(orig_rel), failed),
2066 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2067 errtableconstraint(orig_rel, failed)));
2068 }
2069 }
2070}
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:2149
char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, Bitmapset *modifiedCols, int maxfieldlen)
Definition: execMain.c:2381
AttrNumber ExecRelGenVirtualNotNull(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, List *notnull_virtual_attrs)
Definition: execMain.c:2084
static const char * ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
Definition: execMain.c:1768
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1301
Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1361
Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1382
#define RelationGetRelid(relation)
Definition: rel.h:514
#define RelationGetDescr(relation)
Definition: rel.h:540
Definition: attmap.h:35
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:618
bool has_not_null
Definition: tupdesc.h:45
TupleConstr * constr
Definition: tupdesc.h:141
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:192
static bool slot_attisnull(TupleTableSlot *slot, int attnum)
Definition: tuptable.h:385

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

Definition at line 704 of file execUtils.c.

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

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

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

◆ execCurrentOf()

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

Definition at line 44 of file execCurrent.c.

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

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

Referenced by TidListEval().

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 562 of file execProcnode.c.

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

References bms_free(), check_stack_depth(), PlanState::chgParam, elog, ERROR, ExecEndAgg(), ExecEndAppend(), ExecEndBitmapAnd(), ExecEndBitmapHeapScan(), ExecEndBitmapIndexScan(), ExecEndBitmapOr(), ExecEndCteScan(), ExecEndCustomScan(), ExecEndForeignScan(), ExecEndFunctionScan(), ExecEndGather(), ExecEndGatherMerge(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndIncrementalSort(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMemoize(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndProjectSet(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSampleScan(), ExecEndSeqScan(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndTableFuncScan(), ExecEndTidRangeScan(), ExecEndTidScan(), ExecEndUnique(), ExecEndWindowAgg(), and nodeTag.

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

◆ ExecEvalExpr()

◆ ExecEvalExprNoReturn()

static void ExecEvalExprNoReturn ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 415 of file executor.h.

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

References Assert(), and PG_USED_FOR_ASSERTS_ONLY.

Referenced by ExecEvalExprNoReturnSwitchContext().

◆ ExecEvalExprNoReturnSwitchContext()

static void ExecEvalExprNoReturnSwitchContext ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 455 of file executor.h.

457{
458 MemoryContext oldContext;
459
460 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
461 ExecEvalExprNoReturn(state, econtext);
462 MemoryContextSwitchTo(oldContext);
463}
static void ExecEvalExprNoReturn(ExprState *state, ExprContext *econtext)
Definition: executor.h:415

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

Referenced by advance_aggregates(), and ExecProject().

◆ ExecEvalExprSwitchContext()

◆ ExecFilterJunk()

TupleTableSlot * ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 247 of file execJunk.c.

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

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

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

◆ ExecFindJunkAttribute()

AttrNumber ExecFindJunkAttribute ( JunkFilter junkfilter,
const char *  attrName 
)

Definition at line 210 of file execJunk.c.

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

References ExecFindJunkAttributeInTlist(), and JunkFilter::jf_targetList.

◆ ExecFindJunkAttributeInTlist()

AttrNumber ExecFindJunkAttributeInTlist ( List targetlist,
const char *  attrName 
)

Definition at line 222 of file execJunk.c.

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

References InvalidAttrNumber, lfirst, and TargetEntry::resno.

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

◆ ExecFindRowMark()

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

Definition at line 2546 of file execMain.c.

2547{
2548 if (rti > 0 && rti <= estate->es_range_table_size &&
2549 estate->es_rowmarks != NULL)
2550 {
2551 ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2552
2553 if (erm)
2554 return erm;
2555 }
2556 if (!missing_ok)
2557 elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2558 return NULL;
2559}

References elog, ERROR, and EState::es_rowmarks.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecGetAllNullSlot()

TupleTableSlot * ExecGetAllNullSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1273 of file execUtils.c.

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

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

Referenced by ExecProcessReturning().

◆ ExecGetAllUpdatedCols()

Bitmapset * ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1418 of file execUtils.c.

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

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

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

◆ ExecGetAncestorResultRels()

List * ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1420 of file execMain.c.

1421{
1422 ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1423 Relation partRel = resultRelInfo->ri_RelationDesc;
1424 Oid rootRelOid;
1425
1426 if (!partRel->rd_rel->relispartition)
1427 elog(ERROR, "cannot find ancestors of a non-partition result relation");
1428 Assert(rootRelInfo != NULL);
1429 rootRelOid = RelationGetRelid(rootRelInfo->ri_RelationDesc);
1430 if (resultRelInfo->ri_ancestorResultRels == NIL)
1431 {
1432 ListCell *lc;
1434 List *ancResultRels = NIL;
1435
1436 foreach(lc, oids)
1437 {
1438 Oid ancOid = lfirst_oid(lc);
1439 Relation ancRel;
1440 ResultRelInfo *rInfo;
1441
1442 /*
1443 * Ignore the root ancestor here, and use ri_RootResultRelInfo
1444 * (below) for it instead. Also, we stop climbing up the
1445 * hierarchy when we find the table that was mentioned in the
1446 * query.
1447 */
1448 if (ancOid == rootRelOid)
1449 break;
1450
1451 /*
1452 * All ancestors up to the root target relation must have been
1453 * locked by the planner or AcquireExecutorLocks().
1454 */
1455 ancRel = table_open(ancOid, NoLock);
1456 rInfo = makeNode(ResultRelInfo);
1457
1458 /* dummy rangetable index */
1459 InitResultRelInfo(rInfo, ancRel, 0, NULL,
1460 estate->es_instrument);
1461 ancResultRels = lappend(ancResultRels, rInfo);
1462 }
1463 ancResultRels = lappend(ancResultRels, rootRelInfo);
1464 resultRelInfo->ri_ancestorResultRels = ancResultRels;
1465 }
1466
1467 /* We must have found some ancestor */
1468 Assert(resultRelInfo->ri_ancestorResultRels != NIL);
1469
1470 return resultRelInfo->ri_ancestorResultRels;
1471}
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
Definition: execMain.c:1243
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, get_partition_ancestors(), InitResultRelInfo(), lappend(), lfirst_oid, makeNode, NIL, NoLock, RelationData::rd_rel, RelationGetRelid, ResultRelInfo::ri_ancestorResultRels, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_RootResultRelInfo, and table_open().

Referenced by ExecCrossPartitionUpdateForeignKey().

◆ ExecGetChildToRootMap()

TupleConversionMap * ExecGetChildToRootMap ( ResultRelInfo resultRelInfo)

Definition at line 1300 of file execUtils.c.

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

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

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

◆ ExecGetCommonChildSlotOps()

const TupleTableSlotOps * ExecGetCommonChildSlotOps ( PlanState ps)

Definition at line 563 of file execUtils.c.

564{
565 PlanState *planstates[2];
566
567 planstates[0] = outerPlanState(ps);
568 planstates[1] = innerPlanState(ps);
569 return ExecGetCommonSlotOps(planstates, 2);
570}
const TupleTableSlotOps * ExecGetCommonSlotOps(PlanState **planstates, int nplans)
Definition: execUtils.c:536
#define innerPlanState(node)
Definition: execnodes.h:1254
struct parser_state ps

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

Referenced by build_hash_table().

◆ ExecGetCommonSlotOps()

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

Definition at line 536 of file execUtils.c.

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

References ExecGetResultSlotOps(), and i.

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

◆ ExecGetExtraUpdatedCols()

Bitmapset * ExecGetExtraUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1403 of file execUtils.c.

1404{
1405 /* Compute the info if we didn't already */
1406 if (!relinfo->ri_extraUpdatedCols_valid)
1407 ExecInitGenerated(relinfo, estate, CMD_UPDATE);
1408 return relinfo->ri_extraUpdatedCols;
1409}
void ExecInitGenerated(ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype)
bool ri_extraUpdatedCols_valid
Definition: execnodes.h:500
Bitmapset * ri_extraUpdatedCols
Definition: execnodes.h:498

References CMD_UPDATE, ExecInitGenerated(), ResultRelInfo::ri_extraUpdatedCols, and ResultRelInfo::ri_extraUpdatedCols_valid.

Referenced by ExecGetAllUpdatedCols(), and index_unchanged_by_update().

◆ ExecGetInsertedCols()

Bitmapset * ExecGetInsertedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1361 of file execUtils.c.

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

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

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

◆ ExecGetJunkAttribute()

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

Definition at line 222 of file executor.h.

223{
224 Assert(attno > 0);
225 return slot_getattr(slot, attno, isNull);
226}
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:399

References Assert(), and slot_getattr().

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

◆ ExecGetRangeTableRelation()

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

Definition at line 825 of file execUtils.c.

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

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

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

◆ ExecGetResultRelCheckAsUser()

Oid ExecGetResultRelCheckAsUser ( ResultRelInfo relInfo,
EState estate 
)

Definition at line 1489 of file execUtils.c.

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

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

Referenced by create_foreign_modify().

◆ ExecGetResultSlotOps()

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

Definition at line 504 of file execUtils.c.

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

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

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

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot * ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1248 of file execUtils.c.

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

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

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

◆ ExecGetRootToChildMap()

TupleConversionMap * ExecGetRootToChildMap ( ResultRelInfo resultRelInfo,
EState estate 
)

Definition at line 1326 of file execUtils.c.

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

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

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

◆ ExecGetTriggerNewSlot()

TupleTableSlot * ExecGetTriggerNewSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1226 of file execUtils.c.

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

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

Referenced by AfterTriggerExecute(), and AfterTriggerSaveEvent().

◆ ExecGetTriggerOldSlot()

TupleTableSlot * ExecGetTriggerOldSlot ( EState estate,
ResultRelInfo relInfo 
)

◆ ExecGetTriggerResultRel()

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

Definition at line 1344 of file execMain.c.

1346{
1347 ResultRelInfo *rInfo;
1348 ListCell *l;
1349 Relation rel;
1350 MemoryContext oldcontext;
1351
1352 /* Search through the query result relations */
1353 foreach(l, estate->es_opened_result_relations)
1354 {
1355 rInfo = lfirst(l);
1356 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1357 return rInfo;
1358 }
1359
1360 /*
1361 * Search through the result relations that were created during tuple
1362 * routing, if any.
1363 */
1364 foreach(l, estate->es_tuple_routing_result_relations)
1365 {
1366 rInfo = (ResultRelInfo *) lfirst(l);
1367 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1368 return rInfo;
1369 }
1370
1371 /* Nope, but maybe we already made an extra ResultRelInfo for it */
1372 foreach(l, estate->es_trig_target_relations)
1373 {
1374 rInfo = (ResultRelInfo *) lfirst(l);
1375 if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1376 return rInfo;
1377 }
1378 /* Nope, so we need a new one */
1379
1380 /*
1381 * Open the target relation's relcache entry. We assume that an
1382 * appropriate lock is still held by the backend from whenever the trigger
1383 * event got queued, so we need take no new lock here. Also, we need not
1384 * recheck the relkind, so no need for CheckValidResultRel.
1385 */
1386 rel = table_open(relid, NoLock);
1387
1388 /*
1389 * Make the new entry in the right context.
1390 */
1391 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1392 rInfo = makeNode(ResultRelInfo);
1393 InitResultRelInfo(rInfo,
1394 rel,
1395 0, /* dummy rangetable index */
1396 rootRelInfo,
1397 estate->es_instrument);
1398 estate->es_trig_target_relations =
1399 lappend(estate->es_trig_target_relations, rInfo);
1400 MemoryContextSwitchTo(oldcontext);
1401
1402 /*
1403 * Currently, we don't need any index information in ResultRelInfos used
1404 * only for triggers, so no need to call ExecOpenIndices.
1405 */
1406
1407 return rInfo;
1408}

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

Referenced by afterTriggerInvokeEvents().

◆ ExecGetUpdatedCols()

Bitmapset * ExecGetUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1382 of file execUtils.c.

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

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

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

◆ ExecGetUpdateNewTuple()

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

Definition at line 812 of file nodeModifyTable.c.

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

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

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

◆ ExecInitCheck()

ExprState * ExecInitCheck ( List qual,
PlanState parent 
)

Definition at line 315 of file execExpr.c.

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

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

Referenced by ExecPrepareCheck().

◆ ExecInitExpr()

ExprState * ExecInitExpr ( Expr node,
PlanState parent 
)

Definition at line 143 of file execExpr.c.

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

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

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

◆ ExecInitExprList()

List * ExecInitExprList ( List nodes,
PlanState parent 
)

Definition at line 335 of file execExpr.c.

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

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

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

◆ ExecInitExprWithParams()

ExprState * ExecInitExprWithParams ( Expr node,
ParamListInfo  ext_params 
)

Definition at line 180 of file execExpr.c.

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

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

Referenced by exec_eval_simple_expr(), and InitPartitionPruneContext().

◆ ExecInitExtraTupleSlot()

◆ ExecInitFunctionResultSet()

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

Definition at line 444 of file execSRF.c.

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

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

Referenced by ExecInitProjectSet().

◆ ExecInitJunkFilter()

JunkFilter * ExecInitJunkFilter ( List targetList,
TupleTableSlot slot 
)

Definition at line 60 of file execJunk.c.

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

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

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

◆ ExecInitJunkFilterConversion()

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

Definition at line 137 of file execJunk.c.

140{
141 JunkFilter *junkfilter;
142 int cleanLength;
143 AttrNumber *cleanMap;
144 ListCell *t;
145 int i;
146
147 /*
148 * Use the given slot, or make a new slot if we weren't given one.
149 */
150 if (slot)
151 ExecSetSlotDescriptor(slot, cleanTupType);
152 else
153 slot = MakeSingleTupleTableSlot(cleanTupType, &TTSOpsVirtual);
154
155 /*
156 * Calculate the mapping between the original tuple's attributes and the
157 * "clean" tuple's attributes.
158 *
159 * The "map" is an array of "cleanLength" attribute numbers, i.e. one
160 * entry for every attribute of the "clean" tuple. The value of this entry
161 * is the attribute number of the corresponding attribute of the
162 * "original" tuple. We store zero for any deleted attributes, marking
163 * that a NULL is needed in the output tuple.
164 */
165 cleanLength = cleanTupType->natts;
166 if (cleanLength > 0)
167 {
168 cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
169 t = list_head(targetList);
170 for (i = 0; i < cleanLength; i++)
171 {
172 if (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 */
193 junkfilter = makeNode(JunkFilter);
194
195 junkfilter->jf_targetList = targetList;
196 junkfilter->jf_cleanTupType = cleanTupType;
197 junkfilter->jf_cleanMap = cleanMap;
198 junkfilter->jf_resultSlot = slot;
199
200 return junkfilter;
201}
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

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

Referenced by init_execution_state().

◆ ExecInitNode()

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

Definition at line 142 of file execProcnode.c.

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

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(), PlanState::initPlan, Plan::initPlan, InstrAlloc(), PlanState::instrument, IsA, lappend(), lfirst, NIL, and nodeTag.

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

◆ ExecInitNullTupleSlot()

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

Definition at line 2036 of file execTuples.c.

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

References ExecInitExtraTupleSlot(), and ExecStoreAllNullTuple().

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

◆ ExecInitQual()

ExprState * ExecInitQual ( List qual,
PlanState parent 
)

Definition at line 229 of file execExpr.c.

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

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

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

◆ ExecInitRangeTable()

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

Definition at line 773 of file execUtils.c.

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

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

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

◆ ExecInitResultRelation()

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

Definition at line 880 of file execUtils.c.

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

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

Referenced by CopyFrom(), and ExecInitModifyTable().

◆ ExecInitResultSlot()

void ExecInitResultSlot ( PlanState planstate,
const TupleTableSlotOps tts_ops 
)

Definition at line 1968 of file execTuples.c.

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

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

Referenced by ExecConditionalAssignProjectionInfo(), and ExecInitResultTupleSlotTL().

◆ ExecInitResultTupleSlotTL()

◆ ExecInitResultTypeTL()

◆ ExecInitScanTupleSlot()

◆ ExecInitTableFunctionResult()

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

Definition at line 56 of file execSRF.c.

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

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

Referenced by ExecInitFunctionScan().

◆ ExecInsertIndexTuples()

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

Definition at line 309 of file execIndexing.c.

317{
318 ItemPointer tupleid = &slot->tts_tid;
319 List *result = NIL;
320 int i;
321 int numIndices;
322 RelationPtr relationDescs;
323 Relation heapRelation;
324 IndexInfo **indexInfoArray;
325 ExprContext *econtext;
327 bool isnull[INDEX_MAX_KEYS];
328
329 Assert(ItemPointerIsValid(tupleid));
330
331 /*
332 * Get information from the result relation info structure.
333 */
334 numIndices = resultRelInfo->ri_NumIndices;
335 relationDescs = resultRelInfo->ri_IndexRelationDescs;
336 indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
337 heapRelation = resultRelInfo->ri_RelationDesc;
338
339 /* Sanity check: slot must belong to the same rel as the resultRelInfo. */
340 Assert(slot->tts_tableOid == RelationGetRelid(heapRelation));
341
342 /*
343 * We will use the EState's per-tuple context for evaluating predicates
344 * and index expressions (creating it if it's not already there).
345 */
346 econtext = GetPerTupleExprContext(estate);
347
348 /* Arrange for econtext's scan tuple to be the tuple under test */
349 econtext->ecxt_scantuple = slot;
350
351 /*
352 * for each index, form and insert the index tuple
353 */
354 for (i = 0; i < numIndices; i++)
355 {
356 Relation indexRelation = relationDescs[i];
357 IndexInfo *indexInfo;
358 bool applyNoDupErr;
359 IndexUniqueCheck checkUnique;
360 bool indexUnchanged;
361 bool satisfiesConstraint;
362
363 if (indexRelation == NULL)
364 continue;
365
366 indexInfo = indexInfoArray[i];
367
368 /* If the index is marked as read-only, ignore it */
369 if (!indexInfo->ii_ReadyForInserts)
370 continue;
371
372 /*
373 * Skip processing of non-summarizing indexes if we only update
374 * summarizing indexes
375 */
376 if (onlySummarizing && !indexInfo->ii_Summarizing)
377 continue;
378
379 /* Check for partial index */
380 if (indexInfo->ii_Predicate != NIL)
381 {
382 ExprState *predicate;
383
384 /*
385 * If predicate state not set up yet, create it (in the estate's
386 * per-query context)
387 */
388 predicate = indexInfo->ii_PredicateState;
389 if (predicate == NULL)
390 {
391 predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
392 indexInfo->ii_PredicateState = predicate;
393 }
394
395 /* Skip this index-update if the predicate isn't satisfied */
396 if (!ExecQual(predicate, econtext))
397 continue;
398 }
399
400 /*
401 * FormIndexDatum fills in its values and isnull parameters with the
402 * appropriate values for the column(s) of the index.
403 */
404 FormIndexDatum(indexInfo,
405 slot,
406 estate,
407 values,
408 isnull);
409
410 /* Check whether to apply noDupErr to this index */
411 applyNoDupErr = noDupErr &&
412 (arbiterIndexes == NIL ||
413 list_member_oid(arbiterIndexes,
414 indexRelation->rd_index->indexrelid));
415
416 /*
417 * The index AM does the actual insertion, plus uniqueness checking.
418 *
419 * For an immediate-mode unique index, we just tell the index AM to
420 * throw error if not unique.
421 *
422 * For a deferrable unique index, we tell the index AM to just detect
423 * possible non-uniqueness, and we add the index OID to the result
424 * list if further checking is needed.
425 *
426 * For a speculative insertion (used by INSERT ... ON CONFLICT), do
427 * the same as for a deferrable unique index.
428 */
429 if (!indexRelation->rd_index->indisunique)
430 checkUnique = UNIQUE_CHECK_NO;
431 else if (applyNoDupErr)
432 checkUnique = UNIQUE_CHECK_PARTIAL;
433 else if (indexRelation->rd_index->indimmediate)
434 checkUnique = UNIQUE_CHECK_YES;
435 else
436 checkUnique = UNIQUE_CHECK_PARTIAL;
437
438 /*
439 * There's definitely going to be an index_insert() call for this
440 * index. If we're being called as part of an UPDATE statement,
441 * consider if the 'indexUnchanged' = true hint should be passed.
442 */
443 indexUnchanged = update && index_unchanged_by_update(resultRelInfo,
444 estate,
445 indexInfo,
446 indexRelation);
447
448 satisfiesConstraint =
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;
475 CEOUC_WAIT_MODE waitMode;
476
477 if (applyNoDupErr)
478 {
479 violationOK = true;
481 }
482 else if (!indexRelation->rd_index->indimmediate)
483 {
484 violationOK = true;
485 waitMode = CEOUC_NOWAIT;
486 }
487 else
488 {
489 violationOK = false;
490 waitMode = CEOUC_WAIT;
491 }
492
493 satisfiesConstraint =
495 indexRelation, indexInfo,
496 tupleid, values, isnull,
497 estate, false,
498 waitMode, violationOK, NULL);
499 }
500
501 if ((checkUnique == UNIQUE_CHECK_PARTIAL ||
502 indexInfo->ii_ExclusionOps != NULL) &&
503 !satisfiesConstraint)
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
Definition: execIndexing.c:123
@ CEOUC_NOWAIT
Definition: execIndexing.c:125
@ CEOUC_LIVELOCK_PREVENTING_WAIT
Definition: execIndexing.c:126
IndexUniqueCheck
Definition: genam.h:141
@ UNIQUE_CHECK_NO
Definition: genam.h:142
@ UNIQUE_CHECK_PARTIAL
Definition: genam.h:144
@ UNIQUE_CHECK_YES
Definition: genam.h:143
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:214
Oid tts_tableOid
Definition: tuptable.h:130
ItemPointerData tts_tid
Definition: tuptable.h:129

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

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

◆ ExecLookupResultRelByOid()

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

Definition at line 4567 of file nodeModifyTable.c.

4569{
4570 if (node->mt_resultOidHash)
4571 {
4572 /* Use the pre-built hash table to locate the rel */
4573 MTTargetRelLookup *mtlookup;
4574
4575 mtlookup = (MTTargetRelLookup *)
4576 hash_search(node->mt_resultOidHash, &resultoid, HASH_FIND, NULL);
4577 if (mtlookup)
4578 {
4579 if (update_cache)
4580 {
4581 node->mt_lastResultOid = resultoid;
4582 node->mt_lastResultIndex = mtlookup->relationIndex;
4583 }
4584 return node->resultRelInfo + mtlookup->relationIndex;
4585 }
4586 }
4587 else
4588 {
4589 /* With few target rels, just search the ResultRelInfo array */
4590 for (int ndx = 0; ndx < node->mt_nrels; ndx++)
4591 {
4592 ResultRelInfo *rInfo = node->resultRelInfo + ndx;
4593
4594 if (RelationGetRelid(rInfo->ri_RelationDesc) == resultoid)
4595 {
4596 if (update_cache)
4597 {
4598 node->mt_lastResultOid = resultoid;
4599 node->mt_lastResultIndex = ndx;
4600 }
4601 return rInfo;
4602 }
4603 }
4604 }
4605
4606 if (!missing_ok)
4607 elog(ERROR, "incorrect result relation OID %u", resultoid);
4608 return NULL;
4609}
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:1402
HTAB * mt_resultOidHash
Definition: execnodes.h:1424

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

Referenced by ExecFindPartition(), and ExecModifyTable().

◆ ExecMakeFunctionResultSet()

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

Definition at line 497 of file execSRF.c.

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

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

Referenced by ExecProjectSRF().

◆ ExecMakeTableFunctionResult()

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

Definition at line 101 of file execSRF.c.

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

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

Referenced by FunctionNext().

◆ ExecMarkPos()

void ExecMarkPos ( PlanState node)

Definition at line 327 of file execAmi.c.

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

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

Referenced by ExecMergeJoin(), and ExecResultMarkPos().

◆ ExecMaterializesOutput()

bool ExecMaterializesOutput ( NodeTag  plantype)

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

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

◆ ExecOpenIndices()

void ExecOpenIndices ( ResultRelInfo resultRelInfo,
bool  speculative 
)

Definition at line 160 of file execIndexing.c.

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

References Assert(), BuildIndexInfo(), BuildSpeculativeIndexInfo(), i, IndexInfo::ii_Unique, index_open(), len, lfirst_oid, list_free(), list_length(), palloc(), RelationData::rd_index, 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 
)

Definition at line 742 of file execUtils.c.

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

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

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

◆ ExecPartitionCheck()

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

Definition at line 1846 of file execMain.c.

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

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

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

◆ ExecPartitionCheckEmitError()

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

Definition at line 1899 of file execMain.c.

1902{
1903 Oid root_relid;
1904 TupleDesc tupdesc;
1905 char *val_desc;
1906 Bitmapset *modifiedCols;
1907
1908 /*
1909 * If the tuple has been routed, it's been converted to the partition's
1910 * rowtype, which might differ from the root table's. We must convert it
1911 * back to the root table's rowtype so that val_desc in the error message
1912 * matches the input tuple.
1913 */
1914 if (resultRelInfo->ri_RootResultRelInfo)
1915 {
1916 ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
1917 TupleDesc old_tupdesc;
1918 AttrMap *map;
1919
1920 root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
1921 tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
1922
1923 old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1924 /* a reverse map */
1925 map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc, false);
1926
1927 /*
1928 * Partition-specific slot's tupdesc can't be changed, so allocate a
1929 * new one.
1930 */
1931 if (map != NULL)
1932 slot = execute_attr_map_slot(map, slot,
1934 modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
1935 ExecGetUpdatedCols(rootrel, estate));
1936 }
1937 else
1938 {
1939 root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1940 tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1941 modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
1942 ExecGetUpdatedCols(resultRelInfo, estate));
1943 }
1944
1945 val_desc = ExecBuildSlotValueDescription(root_relid,
1946 slot,
1947 tupdesc,
1948 modifiedCols,
1949 64);
1950 ereport(ERROR,
1951 (errcode(ERRCODE_CHECK_VIOLATION),
1952 errmsg("new row for relation \"%s\" violates partition constraint",
1954 val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
1955 errtable(resultRelInfo->ri_RelationDesc)));
1956}
int errtable(Relation rel)
Definition: relcache.c:6049

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

Referenced by ExecCrossPartitionUpdate(), and ExecPartitionCheck().

◆ ExecPrepareCheck()

ExprState * ExecPrepareCheck ( List qual,
EState estate 
)

Definition at line 816 of file execExpr.c.

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

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

Referenced by ExecPartitionCheck().

◆ ExecPrepareExpr()

ExprState * ExecPrepareExpr ( Expr node,
EState estate 
)

◆ ExecPrepareExprList()

List * ExecPrepareExprList ( List nodes,
EState estate 
)

Definition at line 839 of file execExpr.c.

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

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

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

◆ ExecPrepareQual()

ExprState * ExecPrepareQual ( List qual,
EState estate 
)

Definition at line 793 of file execExpr.c.

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

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

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

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

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

◆ ExecQual()

static bool ExecQual ( ExprState state,
ExprContext econtext 
)
inlinestatic

Definition at line 516 of file executor.h.

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

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

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

◆ ExecQualAndReset()

static bool ExecQualAndReset ( ExprState state,
ExprContext econtext 
)
inlinestatic

◆ ExecRelationIsTargetRelation()

bool ExecRelationIsTargetRelation ( EState estate,
Index  scanrelid 
)

Definition at line 729 of file execUtils.c.

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

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

◆ ExecRelGenVirtualNotNull()

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

Definition at line 2084 of file execMain.c.

2086{
2087 Relation rel = resultRelInfo->ri_RelationDesc;
2088 ExprContext *econtext;
2089 MemoryContext oldContext;
2090
2091 /*
2092 * We implement this by building a NullTest node for each virtual
2093 * generated column, which we cache in resultRelInfo, and running those
2094 * through ExecCheck().
2095 */
2096 if (resultRelInfo->ri_GenVirtualNotNullConstraintExprs == NULL)
2097 {
2098 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
2100 palloc0_array(ExprState *, list_length(notnull_virtual_attrs));
2101
2102 foreach_int(attnum, notnull_virtual_attrs)
2103 {
2105 NullTest *nnulltest;
2106
2107 /* "generated_expression IS NOT NULL" check. */
2108 nnulltest = makeNode(NullTest);
2109 nnulltest->arg = (Expr *) build_generation_expression(rel, attnum);
2110 nnulltest->nulltesttype = IS_NOT_NULL;
2111 nnulltest->argisrow = false;
2112 nnulltest->location = -1;
2113
2114 resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i] =
2115 ExecPrepareExpr((Expr *) nnulltest, estate);
2116 }
2117 MemoryContextSwitchTo(oldContext);
2118 }
2119
2120 /*
2121 * We will use the EState's per-tuple context for evaluating virtual
2122 * generated column not null constraint expressions (creating it if it's
2123 * not already there).
2124 */
2125 econtext = GetPerTupleExprContext(estate);
2126
2127 /* Arrange for econtext's scan tuple to be the tuple under test */
2128 econtext->ecxt_scantuple = slot;
2129
2130 /* And evaluate the check constraints for virtual generated column */
2131 foreach_int(attnum, notnull_virtual_attrs)
2132 {
2134 ExprState *exprstate = resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i];
2135
2136 Assert(exprstate != NULL);
2137 if (!ExecCheck(exprstate, econtext))
2138 return attnum;
2139 }
2140
2141 /* InvalidAttrNumber result means no error */
2142 return InvalidAttrNumber;
2143}
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
@ IS_NOT_NULL
Definition: primnodes.h:1963
Node * build_generation_expression(Relation rel, int attrno)
NullTestType nulltesttype
Definition: primnodes.h:1970
ParseLoc location
Definition: primnodes.h:1973
Expr * arg
Definition: primnodes.h:1969
ExprState ** ri_GenVirtualNotNullConstraintExprs
Definition: execnodes.h:561

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

Referenced by ATRewriteTable(), and ExecConstraints().

◆ ExecReScan()

void ExecReScan ( PlanState node)

Definition at line 77 of file execAmi.c.

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

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

Definition at line 376 of file execAmi.c.

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

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

Referenced by ExecMergeJoin(), and ExecResultRestrPos().

◆ ExecScan()

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

Definition at line 47 of file execScan.c.

50{
51 EPQState *epqstate;
52 ExprState *qual;
53 ProjectionInfo *projInfo;
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,
60 accessMtd,
61 recheckMtd,
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:152
struct EPQState * es_epq_active
Definition: execnodes.h:742
ExprState * qual
Definition: execnodes.h:1180

References EState::es_epq_active, ExecScanExtended(), 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)

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 epqScanDone 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(), IsA, nodeTag, PlanState::plan, ScanState::ps, EPQState::relsubs_blocked, EPQState::relsubs_done, ScanState::ss_ScanTupleSlot, and PlanState::state.

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

◆ ExecSetExecProcNode()

void ExecSetExecProcNode ( PlanState node,
ExecProcNodeMtd  function 
)

Definition at line 430 of file execProcnode.c.

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

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

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

◆ ExecSetTupleBound()

void ExecSetTupleBound ( int64  tuples_needed,
PlanState child_node 
)

Definition at line 848 of file execProcnode.c.

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

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

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

◆ ExecShutdownNode()

void ExecShutdownNode ( PlanState node)

Definition at line 772 of file execProcnode.c.

773{
774 (void) ExecShutdownNode_walker(node, NULL);
775}
static bool ExecShutdownNode_walker(PlanState *node, void *context)
Definition: execProcnode.c:778

References ExecShutdownNode_walker().

Referenced by ExecutePlan().

◆ ExecSimpleRelationDelete()

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

Definition at line 977 of file execReplication.c.

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

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

Referenced by apply_handle_delete_internal(), and apply_handle_tuple_routing().

◆ ExecSimpleRelationInsert()

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

Definition at line 805 of file execReplication.c.

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

References Assert(), CheckAndReportConflict(), CheckCmdReplicaIdentity(), CMD_INSERT, TupleDescData::constr, CT_INSERT_EXISTS, ExecARInsertTriggers(), ExecBRInsertTriggers(), ExecComputeStoredGenerated(), ExecConstraints(), ExecInsertIndexTuples(), ExecPartitionCheck(), 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 
)

Definition at line 894 of file execReplication.c.

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

References Assert(), CheckAndReportConflict(), CheckCmdReplicaIdentity(), CMD_UPDATE, TupleDescData::constr, CT_UPDATE_EXISTS, EState::es_snapshot, ExecARUpdateTriggers(), ExecBRUpdateTriggers(), ExecComputeStoredGenerated(), ExecConstraints(), ExecInsertIndexTuples(), ExecPartitionCheck(), 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, TupleTableSlot::tts_tid, TU_None, and TU_Summarizing.

Referenced by apply_handle_tuple_routing(), and apply_handle_update_internal().

◆ ExecSupportsBackwardScan()

bool ExecSupportsBackwardScan ( Plan node)

Definition at line 511 of file execAmi.c.

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

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

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

◆ ExecSupportsMarkRestore()

bool ExecSupportsMarkRestore ( Path pathnode)

Definition at line 418 of file execAmi.c.

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

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

Referenced by ExecSupportsMarkRestore(), and final_cost_mergejoin().

◆ ExecTargetListLength()

int ExecTargetListLength ( List targetlist)

Definition at line 1175 of file execUtils.c.

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

References list_length().

Referenced by ExecTypeFromTLInternal().

◆ execTuplesHashPrepare()

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

Definition at line 97 of file execGrouping.c.

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

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

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

◆ execTuplesMatchPrepare()

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

Definition at line 58 of file execGrouping.c.

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

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

Definition at line 2186 of file execTuples.c.

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

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

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

◆ ExecTypeFromTL()

◆ ExecTypeSetColNames()

void ExecTypeSetColNames ( TupleDesc  typeInfo,
List namesList 
)

Definition at line 2219 of file execTuples.c.

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

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

Referenced by ExecEvalWholeRowVar(), and ExecInitExprRec().

◆ ExecUpdateLockMode()

LockTupleMode ExecUpdateLockMode ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2520 of file execMain.c.

2521{
2522 Bitmapset *keyCols;
2523 Bitmapset *updatedCols;
2524
2525 /*
2526 * Compute lock mode to use. If columns that are part of the key have not
2527 * been modified, then we can use a weaker lock, allowing for better
2528 * concurrency.
2529 */
2530 updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2533
2534 if (bms_overlap(keyCols, updatedCols))
2535 return LockTupleExclusive;
2536
2538}
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1418
@ LockTupleExclusive
Definition: lockoptions.h:58
@ LockTupleNoKeyExclusive
Definition: lockoptions.h:56
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Definition: relcache.c:5303
@ INDEX_ATTR_BITMAP_KEY
Definition: relcache.h:69

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

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

◆ executor_errposition()

int executor_errposition ( EState estate,
int  location 
)

Definition at line 936 of file execUtils.c.

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

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

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

◆ ExecutorEnd()

void ExecutorEnd ( QueryDesc queryDesc)

Definition at line 466 of file execMain.c.

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

References ExecutorEnd_hook, and standard_ExecutorEnd().

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

◆ ExecutorFinish()

void ExecutorFinish ( QueryDesc queryDesc)

Definition at line 406 of file execMain.c.

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

References ExecutorFinish_hook, and standard_ExecutorFinish().

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

◆ ExecutorRewind()

void ExecutorRewind ( QueryDesc queryDesc)

Definition at line 536 of file execMain.c.

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

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

Referenced by DoPortalRewind(), and PersistHoldablePortal().

◆ ExecutorRun()

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

Definition at line 297 of file execMain.c.

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

References ExecutorRun_hook, and standard_ExecutorRun().

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

◆ ExecutorStart()

void ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 122 of file execMain.c.

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

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

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

◆ ExecWithCheckOptions()

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

Definition at line 2218 of file execMain.c.

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

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

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

◆ FindTupleHashEntry()

TupleHashEntry FindTupleHashEntry ( TupleHashTable  hashtable,
TupleTableSlot slot,
ExprState eqcomp,
ExprState hashexpr 
)

Definition at line 388 of file execGrouping.c.

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

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

Referenced by ExecHashSubPlan().

◆ FreeExecutorState()

void FreeExecutorState ( EState estate)

Definition at line 192 of file execUtils.c.

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

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

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

◆ FreeExprContext()

void FreeExprContext ( ExprContext econtext,
bool  isCommit 
)

Definition at line 416 of file execUtils.c.

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

References ExprContext::ecxt_estate, ExprContext::ecxt_per_tuple_memory, EState::es_exprcontexts, 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 
)

Definition at line 1061 of file execUtils.c.

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

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

Referenced by c_overpaid(), and overpaid().

◆ GetAttributeByNum()

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

Definition at line 1124 of file execUtils.c.

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

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

◆ InitResultRelInfo()

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

Definition at line 1243 of file execMain.c.

1248{
1249 MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1250 resultRelInfo->type = T_ResultRelInfo;
1251 resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1252 resultRelInfo->ri_RelationDesc = resultRelationDesc;
1253 resultRelInfo->ri_NumIndices = 0;
1254 resultRelInfo->ri_IndexRelationDescs = NULL;
1255 resultRelInfo->ri_IndexRelationInfo = NULL;
1256 resultRelInfo->ri_needLockTagTuple =
1257 IsInplaceUpdateRelation(resultRelationDesc);
1258 /* make a copy so as not to depend on relcache info not changing... */
1259 resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1260 if (resultRelInfo->ri_TrigDesc)
1261 {
1262 int n = resultRelInfo->ri_TrigDesc->numtriggers;
1263
1264 resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1265 palloc0(n * sizeof(FmgrInfo));
1266 resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1267 palloc0(n * sizeof(ExprState *));
1268 if (instrument_options)
1269 resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options, false);
1270 }
1271 else
1272 {
1273 resultRelInfo->ri_TrigFunctions = NULL;
1274 resultRelInfo->ri_TrigWhenExprs = NULL;
1275 resultRelInfo->ri_TrigInstrument = NULL;
1276 }
1277 if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1278 resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
1279 else
1280 resultRelInfo->ri_FdwRoutine = NULL;
1281
1282 /* The following fields are set later if needed */
1283 resultRelInfo->ri_RowIdAttNo = 0;
1284 resultRelInfo->ri_extraUpdatedCols = NULL;
1285 resultRelInfo->ri_projectNew = NULL;
1286 resultRelInfo->ri_newTupleSlot = NULL;
1287 resultRelInfo->ri_oldTupleSlot = NULL;
1288 resultRelInfo->ri_projectNewInfoValid = false;
1289 resultRelInfo->ri_FdwState = NULL;
1290 resultRelInfo->ri_usesFdwDirectModify = false;
1291 resultRelInfo->ri_CheckConstraintExprs = NULL;
1292 resultRelInfo->ri_GenVirtualNotNullConstraintExprs = NULL;
1293 resultRelInfo->ri_GeneratedExprsI = NULL;
1294 resultRelInfo->ri_GeneratedExprsU = NULL;
1295 resultRelInfo->ri_projectReturning = NULL;
1296 resultRelInfo->ri_onConflictArbiterIndexes = NIL;
1297 resultRelInfo->ri_onConflict = NULL;
1298 resultRelInfo->ri_ReturningSlot = NULL;
1299 resultRelInfo->ri_TrigOldSlot = NULL;
1300 resultRelInfo->ri_TrigNewSlot = NULL;
1301 resultRelInfo->ri_AllNullSlot = NULL;
1302 resultRelInfo->ri_MergeActions[MERGE_WHEN_MATCHED] = NIL;
1305 resultRelInfo->ri_MergeJoinCondition = NULL;
1306
1307 /*
1308 * Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
1309 * non-NULL partition_root_rri. For child relations that are part of the
1310 * initial query rather than being dynamically added by tuple routing,
1311 * this field is filled in ExecInitModifyTable().
1312 */
1313 resultRelInfo->ri_RootResultRelInfo = partition_root_rri;
1314 /* Set by ExecGetRootToChildMap */
1315 resultRelInfo->ri_RootToChildMap = NULL;
1316 resultRelInfo->ri_RootToChildMapValid = false;
1317 /* Set by ExecInitRoutingInfo */
1318 resultRelInfo->ri_PartitionTupleSlot = NULL;
1319 resultRelInfo->ri_ChildToRootMap = NULL;
1320 resultRelInfo->ri_ChildToRootMapValid = false;
1321 resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
1322}
#define MemSet(start, val, len)
Definition: c.h:1020
@ MERGE_WHEN_NOT_MATCHED_BY_TARGET
Definition: primnodes.h:2009
@ MERGE_WHEN_NOT_MATCHED_BY_SOURCE
Definition: primnodes.h:2008
@ MERGE_WHEN_MATCHED
Definition: primnodes.h:2007
TriggerDesc * trigdesc
Definition: rel.h:117
ExprState ** ri_CheckConstraintExprs
Definition: execnodes.h:555
TupleTableSlot * ri_PartitionTupleSlot
Definition: execnodes.h:619
OnConflictSetState * ri_onConflict
Definition: execnodes.h:583
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:524
ExprState * ri_MergeJoinCondition
Definition: execnodes.h:589
TupleTableSlot * ri_oldTupleSlot
Definition: execnodes.h:507
struct CopyMultiInsertBuffer * ri_CopyMultiInsertBuffer
Definition: execnodes.h:622
ExprState ** ri_GeneratedExprsI
Definition: execnodes.h:566
void * ri_FdwState
Definition: execnodes.h:536
List * ri_MergeActions[NUM_MERGE_MATCH_KINDS]
Definition: execnodes.h:586
TupleTableSlot * ri_newTupleSlot
Definition: execnodes.h:505
NodeTag type
Definition: execnodes.h:474
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:577
ExprState ** ri_GeneratedExprsU
Definition: execnodes.h:567
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:521
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:518
bool ri_usesFdwDirectModify
Definition: execnodes.h:539
AttrNumber ri_RowIdAttNo
Definition: execnodes.h:495
int numtriggers
Definition: reltrigger.h:50
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:2090

References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), IsInplaceUpdateRelation(), MemSet, MERGE_WHEN_MATCHED, MERGE_WHEN_NOT_MATCHED_BY_SOURCE, MERGE_WHEN_NOT_MATCHED_BY_TARGET, NIL, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, 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, RelationData::trigdesc, 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 
)

Definition at line 301 of file execGrouping.c.

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

References Assert(), TupleHashTableData::cur_eq_func, hash(), TupleHashEntryData::hash, TupleHashTableData::hashtab, TupleHashTableData::in_hash_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 
)

Definition at line 356 of file execGrouping.c.

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

References Assert(), TupleHashTableData::cur_eq_func, 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)

Definition at line 458 of file execUtils.c.

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

References CreateExprContext(), and EState::es_per_tuple_exprcontext.

◆ MultiExecProcNode()

Node * MultiExecProcNode ( PlanState node)

Definition at line 507 of file execProcnode.c.

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

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

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

◆ RegisterExprContextCallback()

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

Definition at line 963 of file execUtils.c.

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

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

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

◆ RelationFindDeletedTupleInfoByIndex()

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

Definition at line 630 of file execReplication.c.

636{
637 Relation idxrel;
639 int skey_attoff;
640 IndexScanDesc scan;
641 TupleTableSlot *scanslot;
642 TypeCacheEntry **eq = NULL;
643 bool isIdxSafeToSkipDuplicates;
645
646 Assert(equalTupleDescs(desc, searchslot->tts_tupleDescriptor));
647 Assert(OidIsValid(idxoid));
648
649 *delete_xid = InvalidTransactionId;
650 *delete_time = 0;
651 *delete_origin = InvalidRepOriginId;
652
653 isIdxSafeToSkipDuplicates = (GetRelationIdentityOrPK(rel) == idxoid);
654
655 scanslot = table_slot_create(rel, NULL);
656
657 idxrel = index_open(idxoid, RowExclusiveLock);
658
659 /* Build scan key. */
660 skey_attoff = build_replindex_scan_key(skey, rel, idxrel, searchslot);
661
662 /*
663 * Start an index scan using SnapshotAny to identify dead tuples that are
664 * not visible under a standard MVCC snapshot. Tuples from transactions
665 * not yet committed or those just committed prior to the scan are
666 * excluded in update_most_recent_deletion_info().
667 */
668 scan = index_beginscan(rel, idxrel, SnapshotAny, NULL, skey_attoff, 0);
669
670 index_rescan(scan, skey, skey_attoff, NULL, 0);
671
672 /* Try to find the tuple */
673 while (index_getnext_slot(scan, ForwardScanDirection, scanslot))
674 {
675 /*
676 * Avoid expensive equality check if the index is primary key or
677 * replica identity index.
678 */
679 if (!isIdxSafeToSkipDuplicates)
680 {
681 if (eq == NULL)
682 eq = palloc0(sizeof(*eq) * scanslot->tts_tupleDescriptor->natts);
683
684 if (!tuples_equal(scanslot, searchslot, eq, NULL))
685 continue;
686 }
687
688 update_most_recent_deletion_info(scanslot, oldestxmin, delete_xid,
689 delete_time, delete_origin);
690 }
691
692 index_endscan(scan);
693
694 index_close(idxrel, NoLock);
695
697
698 return *delete_time != 0;
699}
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, RepOriginId *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 InvalidRepOriginId
Definition: origin.h:33
Oid GetRelationIdentityOrPK(Relation rel)
Definition: relation.c:891
#define InvalidTransactionId
Definition: transam.h:31
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:590

References Assert(), build_replindex_scan_key(), equalTupleDescs(), ExecDropSingleTupleTableSlot(), ForwardScanDirection, GetRelationIdentityOrPK(), index_beginscan(), index_close(), index_endscan(), index_getnext_slot(), INDEX_MAX_KEYS, index_open(), index_rescan(), InvalidRepOriginId, InvalidTransactionId, TupleDescData::natts, NoLock, OidIsValid, palloc0(), PG_USED_FOR_ASSERTS_ONLY, RelationGetDescr, RowExclusiveLock, SnapshotAny, table_slot_create(), TupleTableSlot::tts_tupleDescriptor, tuples_equal(), and update_most_recent_deletion_info().

Referenced by FindDeletedTupleInLocalRel().

◆ RelationFindDeletedTupleInfoSeq()

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

Definition at line 561 of file execReplication.c.

566{
567 TupleTableSlot *scanslot;
568 TableScanDesc scan;
569 TypeCacheEntry **eq;
570 Bitmapset *indexbitmap;
572
573 Assert(equalTupleDescs(desc, searchslot->tts_tupleDescriptor));
574
575 *delete_xid = InvalidTransactionId;
576 *delete_origin = InvalidRepOriginId;
577 *delete_time = 0;
578
579 /*
580 * If the relation has a replica identity key or a primary key that is
581 * unusable for locating deleted tuples (see
582 * IsIndexUsableForFindingDeletedTuple), a full table scan becomes
583 * necessary. In such cases, comparing the entire tuple is not required,
584 * since the remote tuple might not include all column values. Instead,
585 * the indexed columns alone are sufficient to identify the target tuple
586 * (see logicalrep_rel_mark_updatable).
587 */
588 indexbitmap = RelationGetIndexAttrBitmap(rel,
590
591 /* fallback to PK if no replica identity */
592 if (!indexbitmap)
593 indexbitmap = RelationGetIndexAttrBitmap(rel,
595
596 eq = palloc0(sizeof(*eq) * searchslot->tts_tupleDescriptor->natts);
597
598 /*
599 * Start a heap scan using SnapshotAny to identify dead tuples that are
600 * not visible under a standard MVCC snapshot. Tuples from transactions
601 * not yet committed or those just committed prior to the scan are
602 * excluded in update_most_recent_deletion_info().
603 */
604 scan = table_beginscan(rel, SnapshotAny, 0, NULL);
605 scanslot = table_slot_create(rel, NULL);
606
607 table_rescan(scan, NULL);
608
609 /* Try to find the tuple */
610 while (table_scan_getnextslot(scan, ForwardScanDirection, scanslot))
611 {
612 if (!tuples_equal(scanslot, searchslot, eq, indexbitmap))
613 continue;
614
615 update_most_recent_deletion_info(scanslot, oldestxmin, delete_xid,
616 delete_time, delete_origin);
617 }
618
619 table_endscan(scan);
621
622 return *delete_time != 0;
623}
@ 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:985
static void table_rescan(TableScanDesc scan, ScanKeyData *key)
Definition: tableam.h:994
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1020
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key)
Definition: tableam.h:876

References Assert(), equalTupleDescs(), ExecDropSingleTupleTableSlot(), ForwardScanDirection, INDEX_ATTR_BITMAP_IDENTITY_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, InvalidRepOriginId, InvalidTransactionId, TupleDescData::natts, palloc0(), PG_USED_FOR_ASSERTS_ONLY, RelationGetDescr, RelationGetIndexAttrBitmap(), SnapshotAny, table_beginscan(), table_endscan(), table_rescan(), table_scan_getnextslot(), table_slot_create(), TupleTableSlot::tts_tupleDescriptor, tuples_equal(), and update_most_recent_deletion_info().

Referenced by FindDeletedTupleInLocalRel().

◆ RelationFindReplTupleByIndex()

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

Definition at line 181 of file execReplication.c.

185{
187 int skey_attoff;
188 IndexScanDesc scan;
189 SnapshotData snap;
190 TransactionId xwait;
191 Relation idxrel;
192 bool found;
193 TypeCacheEntry **eq = NULL;
194 bool isIdxSafeToSkipDuplicates;
195
196 /* Open the index. */
197 idxrel = index_open(idxoid, RowExclusiveLock);
198
199 isIdxSafeToSkipDuplicates = (GetRelationIdentityOrPK(rel) == idxoid);
200
201 InitDirtySnapshot(snap);
202
203 /* Build scan key. */
204 skey_attoff = build_replindex_scan_key(skey, rel, idxrel, searchslot);
205
206 /* Start an index scan. */
207 scan = index_beginscan(rel, idxrel, &snap, NULL, skey_attoff, 0);
208
209retry:
210 found = false;
211
212 index_rescan(scan, skey, skey_attoff, NULL, 0);
213
214 /* Try to find the tuple */
215 while (index_getnext_slot(scan, ForwardScanDirection, outslot))
216 {
217 /*
218 * Avoid expensive equality check if the index is primary key or
219 * replica identity index.
220 */
221 if (!isIdxSafeToSkipDuplicates)
222 {
223 if (eq == NULL)
224 eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
225
226 if (!tuples_equal(outslot, searchslot, eq, NULL))
227 continue;
228 }
229
230 ExecMaterializeSlot(outslot);
231
232 xwait = TransactionIdIsValid(snap.xmin) ?
233 snap.xmin : snap.xmax;
234
235 /*
236 * If the tuple is locked, wait for locking transaction to finish and
237 * retry.
238 */
239 if (TransactionIdIsValid(xwait))
240 {
241 XactLockTableWait(xwait, NULL, NULL, XLTW_None);
242 goto retry;
243 }
244
245 /* Found our tuple and it's not locked */
246 found = true;
247 break;
248 }
249
250 /* Found tuple, try to lock it in the lockmode. */
251 if (found)
252 {
253 TM_FailureData tmfd;
254 TM_Result res;
255
257
258 res = table_tuple_lock(rel, &(outslot->tts_tid), GetActiveSnapshot(),
259 outslot,
260 GetCurrentCommandId(false),
261 lockmode,
263 0 /* don't follow updates */ ,
264 &tmfd);
265
267
268 if (should_refetch_tuple(res, &tmfd))
269 goto retry;
270 }
271
272 index_endscan(scan);
273
274 /* Don't release lock until commit. */
275 index_close(idxrel, NoLock);
276
277 return found;
278}
uint32 TransactionId
Definition: c.h:658
static bool should_refetch_tuple(TM_Result res, TM_FailureData *tmfd)
void XactLockTableWait(TransactionId xid, Relation rel, const ItemPointerData *ctid, XLTW_Oper oper)
Definition: lmgr.c:663
@ XLTW_None
Definition: lmgr.h:26
@ LockWaitBlock
Definition: lockoptions.h:39
Snapshot GetLatestSnapshot(void)
Definition: snapmgr.c:353
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:680
void PopActiveSnapshot(void)
Definition: snapmgr.c:773
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:798
#define InitDirtySnapshot(snapshotdata)
Definition: snapmgr.h:42
TransactionId xmin
Definition: snapshot.h:153
TransactionId xmax
Definition: snapshot.h:154
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:1549
#define TransactionIdIsValid(xid)
Definition: transam.h:41
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:829

References build_replindex_scan_key(), ExecMaterializeSlot(), ForwardScanDirection, GetActiveSnapshot(), GetCurrentCommandId(), GetLatestSnapshot(), GetRelationIdentityOrPK(), index_beginscan(), index_close(), index_endscan(), index_getnext_slot(), INDEX_MAX_KEYS, index_open(), index_rescan(), InitDirtySnapshot, LockWaitBlock, TupleDescData::natts, NoLock, palloc0(), PopActiveSnapshot(), PushActiveSnapshot(), RowExclusiveLock, should_refetch_tuple(), table_tuple_lock(), TransactionIdIsValid, TupleTableSlot::tts_tid, TupleTableSlot::tts_tupleDescriptor, tuples_equal(), XactLockTableWait(), XLTW_None, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by FindReplTupleInLocalRel().

◆ RelationFindReplTupleSeq()

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

Definition at line 368 of file execReplication.c.

370{
371 TupleTableSlot *scanslot;
372 TableScanDesc scan;
373 SnapshotData snap;
374 TypeCacheEntry **eq;
375 TransactionId xwait;
376 bool found;
378
380
381 eq = palloc0(sizeof(*eq) * outslot->tts_tupleDescriptor->natts);
382
383 /* Start a heap scan. */
384 InitDirtySnapshot(snap);
385 scan = table_beginscan(rel, &snap, 0, NULL);
386 scanslot = table_slot_create(rel, NULL);
387
388retry:
389 found = false;
390
391 table_rescan(scan, NULL);
392
393 /* Try to find the tuple */
394 while (table_scan_getnextslot(scan, ForwardScanDirection, scanslot))
395 {
396 if (!tuples_equal(scanslot, searchslot, eq, NULL))
397 continue;
398
399 found = true;
400 ExecCopySlot(outslot, scanslot);
401
402 xwait = TransactionIdIsValid(snap.xmin) ?
403 snap.xmin : snap.xmax;
404
405 /*
406 * If the tuple is locked, wait for locking transaction to finish and
407 * retry.
408 */
409 if (TransactionIdIsValid(xwait))
410 {
411 XactLockTableWait(xwait, NULL, NULL, XLTW_None);
412 goto retry;
413 }
414
415 /* Found our tuple and it's not locked */
416 break;
417 }
418
419 /* Found tuple, try to lock it in the lockmode. */
420 if (found)
421 {
422 TM_FailureData tmfd;
423 TM_Result res;
424
426
427 res = table_tuple_lock(rel, &(outslot->tts_tid), GetActiveSnapshot(),
428 outslot,
429 GetCurrentCommandId(false),
430 lockmode,
432 0 /* don't follow updates */ ,
433 &tmfd);
434
436
437 if (should_refetch_tuple(res, &tmfd))
438 goto retry;
439 }
440
441 table_endscan(scan);
443
444 return found;
445}

References Assert(), equalTupleDescs(), ExecCopySlot(), ExecDropSingleTupleTableSlot(), ForwardScanDirection, GetActiveSnapshot(), GetCurrentCommandId(), GetLatestSnapshot(), InitDirtySnapshot, LockWaitBlock, TupleDescData::natts, palloc0(), 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, TupleTableSlot::tts_tid, TupleTableSlot::tts_tupleDescriptor, tuples_equal(), XactLockTableWait(), XLTW_None, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by FindReplTupleInLocalRel().

◆ ReScanExprContext()

void ReScanExprContext ( ExprContext econtext)

Definition at line 443 of file execUtils.c.

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

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

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

◆ ResetTupleHashTable()

void ResetTupleHashTable ( TupleHashTable  hashtable)

Definition at line 280 of file execGrouping.c.

281{
282 tuplehash_reset(hashtable->hashtab);
283}

References TupleHashTableData::hashtab.

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

◆ standard_ExecutorEnd()

void standard_ExecutorEnd ( QueryDesc queryDesc)

Definition at line 475 of file execMain.c.

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

Definition at line 415 of file execMain.c.

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

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

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

◆ standard_ExecutorRun()

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

Definition at line 307 of file execMain.c.

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

References Assert(), CMD_SELECT, generate_unaccent_rules::dest, 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(), 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 
)

Definition at line 141 of file execMain.c.

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

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

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

◆ TupleHashEntryGetAdditional()

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

Definition at line 189 of file executor.h.

190{
191 if (hashtable->additionalsize > 0)
192 return (char *) entry->firstTuple - hashtable->additionalsize;
193 else
194 return NULL;
195}
MinimalTuple firstTuple
Definition: execnodes.h:849

References TupleHashTableData::additionalsize, 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 175 of file executor.h.

176{
177 return entry->firstTuple;
178}

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

167{
168 return sizeof(TupleHashEntryData);
169}

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

◆ TupleHashTableHash()

uint32 TupleHashTableHash ( TupleHashTable  hashtable,
TupleTableSlot slot 
)

Definition at line 333 of file execGrouping.c.

334{
335 MemoryContext oldContext;
336 uint32 hash;
337
338 hashtable->inputslot = slot;
339 hashtable->in_hash_expr = hashtable->tab_hash_expr;
340
341 /* Need to run the hash functions in short-lived context */
342 oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
343
344 hash = TupleHashTableHash_internal(hashtable->hashtab, NULL);
345
346 MemoryContextSwitchTo(oldContext);
347
348 return hash;
349}

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

Definition at line 989 of file execUtils.c.

992{
993 ExprContext_CB **prev_callback;
994 ExprContext_CB *ecxt_callback;
995
996 prev_callback = &econtext->ecxt_callbacks;
997
998 while ((ecxt_callback = *prev_callback) != NULL)
999 {
1000 if (ecxt_callback->function == function && ecxt_callback->arg == arg)
1001 {
1002 *prev_callback = ecxt_callback->next;
1003 pfree(ecxt_callback);
1004 }
1005 else
1006 prev_callback = &ecxt_callback->next;
1007 }
1008}

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

Referenced by end_MultiFuncCall(), and fmgr_sql().

◆ UpdateChangedParamSet()

void UpdateChangedParamSet ( PlanState node,
Bitmapset newchg 
)

Definition at line 910 of file execUtils.c.

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

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

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

Variable Documentation

◆ ExecutorCheckPerms_hook

PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
extern

Definition at line 74 of file execMain.c.

Referenced by _PG_init(), and ExecCheckPermissions().

◆ ExecutorEnd_hook

PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook
extern

Definition at line 71 of file execMain.c.

Referenced by _PG_init(), and ExecutorEnd().

◆ ExecutorFinish_hook

PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook
extern

Definition at line 70 of file execMain.c.

Referenced by _PG_init(), and ExecutorFinish().

◆ ExecutorRun_hook

PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook
extern

Definition at line 69 of file execMain.c.

Referenced by _PG_init(), and ExecutorRun().

◆ ExecutorStart_hook

PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook
extern

Definition at line 68 of file execMain.c.

Referenced by _PG_init(), and ExecutorStart().