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

Go to the source code of this file.

Data Structures

struct  TupOutputState
 

Macros

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

Typedefs

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

Functions

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

Variables

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

Macro Definition Documentation

◆ do_text_output_oneline

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

Definition at line 522 of file executor.h.

◆ EvalPlanQualSetSlot

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

Definition at line 244 of file executor.h.

◆ EXEC_FLAG_BACKWARD

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

Definition at line 68 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_GENERIC

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

Definition at line 66 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_ONLY

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

Definition at line 65 of file executor.h.

◆ EXEC_FLAG_MARK

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

Definition at line 69 of file executor.h.

◆ EXEC_FLAG_REWIND

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

Definition at line 67 of file executor.h.

◆ EXEC_FLAG_SKIP_TRIGGERS

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

Definition at line 70 of file executor.h.

◆ EXEC_FLAG_WITH_NO_DATA

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

Definition at line 71 of file executor.h.

◆ GetPerTupleExprContext

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

Definition at line 550 of file executor.h.

◆ GetPerTupleMemoryContext

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

Definition at line 555 of file executor.h.

◆ ResetExprContext

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

Definition at line 544 of file executor.h.

◆ ResetPerTupleExprContext

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

Definition at line 559 of file executor.h.

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 473 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 474 of file executor.h.

◆ ExecutorCheckPerms_hook_type

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

Definition at line 94 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 90 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 86 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 79 of file executor.h.

◆ ExecutorStart_hook_type

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

Definition at line 75 of file executor.h.

◆ TupOutputState

Function Documentation

◆ begin_tup_output_tupdesc()

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

Definition at line 2342 of file execTuples.c.

2345 {
2346  TupOutputState *tstate;
2347 
2348  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2349 
2350  tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2351  tstate->dest = dest;
2352 
2353  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2354 
2355  return tstate;
2356 }
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1325
void * palloc(Size size)
Definition: mcxt.c:1316
@ CMD_SELECT
Definition: nodes.h:265
TupleTableSlot * slot
Definition: executor.h:506
DestReceiver * dest
Definition: executor.h:507
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,
int  numCols,
AttrNumber keyColIdx,
const Oid eqfuncoids,
FmgrInfo hashfunctions,
Oid collations,
long  nbuckets,
Size  additionalsize,
MemoryContext  tablecxt,
MemoryContext  tempcxt,
bool  use_variable_hash_iv 
)

Definition at line 254 of file execGrouping.c.

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

References BuildTupleHashTableExt().

◆ BuildTupleHashTableExt()

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

Definition at line 153 of file execGrouping.c.

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

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

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

◆ check_exclusion_constraint()

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

Definition at line 915 of file execIndexing.c.

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

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), and values.

Referenced by IndexCheckExclusion().

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 652 of file execReplication.c.

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

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

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

◆ CheckSubscriptionRelkind()

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

Definition at line 739 of file execReplication.c.

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

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

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

◆ CheckValidResultRel()

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

Definition at line 1026 of file execMain.c.

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

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

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

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 88 of file execUtils.c.

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

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

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

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 304 of file execUtils.c.

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

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 355 of file execUtils.c.

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

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

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

◆ CreateWorkExprContext()

ExprContext* CreateWorkExprContext ( EState estate)

Definition at line 319 of file execUtils.c.

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

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

Referenced by ExecInitAgg().

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 2390 of file execTuples.c.

2391 {
2392  Datum values[1];
2393  bool isnull[1] = {false};
2394 
2395  while (*txt)
2396  {
2397  const char *eol;
2398  int len;
2399 
2400  eol = strchr(txt, '\n');
2401  if (eol)
2402  {
2403  len = eol - txt;
2404  eol++;
2405  }
2406  else
2407  {
2408  len = strlen(txt);
2409  eol = txt + len;
2410  }
2411 
2413  do_tup_output(tstate, values, isnull);
2415  txt = eol;
2416  }
2417 }
void do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
Definition: execTuples.c:2362
void pfree(void *pointer)
Definition: mcxt.c:1520
const void size_t len
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

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

Referenced by ExplainQuery().

◆ do_tup_output()

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

Definition at line 2362 of file execTuples.c.

2363 {
2364  TupleTableSlot *slot = tstate->slot;
2365  int natts = slot->tts_tupleDescriptor->natts;
2366 
2367  /* make sure the slot is clear */
2368  ExecClearTuple(slot);
2369 
2370  /* insert data */
2371  memcpy(slot->tts_values, values, natts * sizeof(Datum));
2372  memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2373 
2374  /* mark slot as containing a virtual tuple */
2375  ExecStoreVirtualTuple(slot);
2376 
2377  /* send the tuple to the receiver */
2378  (void) tstate->dest->receiveSlot(slot, tstate->dest);
2379 
2380  /* clean up */
2381  ExecClearTuple(slot);
2382 }
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1639
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:454

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

2421 {
2422  tstate->dest->rShutdown(tstate->dest);
2423  /* note that destroying the dest is not ours to do */
2425  pfree(tstate);
2426 }
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1341
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 2470 of file execMain.c.

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

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

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

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

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2982 of file execMain.c.

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

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

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

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

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

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

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

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

Referenced by EvalPlanQual(), and ExecLockRows().

◆ EvalPlanQualSetPlan()

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

Definition at line 2581 of file execMain.c.

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

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2598 of file execMain.c.

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

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

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

◆ exec_rt_fetch()

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

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

Definition at line 538 of file execUtils.c.

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

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

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

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 647 of file execUtils.c.

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

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

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

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

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

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

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

◆ ExecBuildParamSetEqual()

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

Definition at line 4103 of file execExpr.c.

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

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

Referenced by ExecInitMemoize().

◆ ExecBuildProjectionInfo()

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

Definition at line 361 of file execExpr.c.

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

References ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, attnum, ExprEvalStep::d, EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_ASSIGN_TMP_MAKE_RO, EEOP_DONE, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), TargetEntry::expr, ExprEvalPushStep(), exprType(), get_typlen(), if(), INNER_VAR, IsA, lfirst_node, makeNode, ExprEvalStep::opcode, OUTER_VAR, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TargetEntry::resno, TupleDescAttr, and ExprState::type.

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

◆ ExecBuildUpdateProjection()

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

Definition at line 521 of file execExpr.c.

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

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

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)

Definition at line 846 of file execExpr.c.

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

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

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

◆ ExecCheckIndexConstraints()

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

Definition at line 527 of file execIndexing.c.

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

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

Referenced by ExecInsert().

◆ ExecCheckPermissions()

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

Definition at line 579 of file execMain.c.

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

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

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

References len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 2037 of file execTuples.c.

2038 {
2039  return ExecTypeFromTLInternal(targetList, true);
2040 }
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
Definition: execTuples.c:2043

References ExecTypeFromTLInternal().

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 231 of file execIndexing.c.

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

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

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

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1577 of file execMain.c.

1578 {
1579  int i;
1580 
1581  for (i = 0; i < estate->es_range_table_size; i++)
1582  {
1583  if (estate->es_relations[i])
1584  table_close(estate->es_relations[i], NoLock);
1585  }
1586 }
#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 1517 of file execMain.c.

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

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

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

◆ ExecConditionalAssignProjectionInfo()

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

Definition at line 558 of file execUtils.c.

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

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

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

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

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

◆ ExecCreateScanSlotFromOuterPlan()

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

Definition at line 659 of file execUtils.c.

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

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

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

◆ execCurrentOf()

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

Definition at line 44 of file execCurrent.c.

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

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

Referenced by TidListEval().

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 557 of file execProcnode.c.

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

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

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

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

◆ ExecFilterJunk()

TupleTableSlot* ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 247 of file execJunk.c.

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

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

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

◆ ExecFindJunkAttribute()

AttrNumber ExecFindJunkAttribute ( JunkFilter junkfilter,
const char *  attrName 
)

Definition at line 210 of file execJunk.c.

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

References ExecFindJunkAttributeInTlist(), and JunkFilter::jf_targetList.

◆ ExecFindJunkAttributeInTlist()

AttrNumber ExecFindJunkAttributeInTlist ( List targetlist,
const char *  attrName 
)

Definition at line 222 of file execJunk.c.

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

References InvalidAttrNumber, lfirst, and TargetEntry::resno.

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

◆ ExecFindRowMark()

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

Definition at line 2377 of file execMain.c.

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

References elog, ERROR, and EState::es_rowmarks.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecGetAllUpdatedCols()

Bitmapset* ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1324 of file execUtils.c.

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

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

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

◆ ExecGetAncestorResultRels()

List* ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1372 of file execMain.c.

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

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

Referenced by ExecCrossPartitionUpdateForeignKey().

◆ ExecGetChildToRootMap()

TupleConversionMap* ExecGetChildToRootMap ( ResultRelInfo resultRelInfo)

Definition at line 1206 of file execUtils.c.

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

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

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

◆ ExecGetExtraUpdatedCols()

Bitmapset* ExecGetExtraUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1309 of file execUtils.c.

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

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

Referenced by ExecGetAllUpdatedCols(), and index_unchanged_by_update().

◆ ExecGetInsertedCols()

Bitmapset* ExecGetInsertedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1267 of file execUtils.c.

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

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

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

◆ ExecGetJunkAttribute()

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

Definition at line 190 of file executor.h.

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

References Assert, and slot_getattr().

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

◆ ExecGetRangeTableRelation()

Relation ExecGetRangeTableRelation ( EState estate,
Index  rti 
)

Definition at line 762 of file execUtils.c.

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

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

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

◆ ExecGetResultRelCheckAsUser()

Oid ExecGetResultRelCheckAsUser ( ResultRelInfo relInfo,
EState estate 
)

Definition at line 1395 of file execUtils.c.

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

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

Referenced by create_foreign_modify().

◆ ExecGetResultSlotOps()

const TupleTableSlotOps* ExecGetResultSlotOps ( PlanState planstate,
bool isfixed 
)

Definition at line 502 of file execUtils.c.

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

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

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

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot* ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1182 of file execUtils.c.

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

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

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

◆ ExecGetRootToChildMap()

TupleConversionMap* ExecGetRootToChildMap ( ResultRelInfo resultRelInfo,
EState estate 
)

Definition at line 1232 of file execUtils.c.

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

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

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

◆ ExecGetTriggerNewSlot()

TupleTableSlot* ExecGetTriggerNewSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1160 of file execUtils.c.

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

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

Referenced by AfterTriggerExecute(), and AfterTriggerSaveEvent().

◆ ExecGetTriggerOldSlot()

TupleTableSlot* ExecGetTriggerOldSlot ( EState estate,
ResultRelInfo relInfo 
)

◆ ExecGetTriggerResultRel()

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

Definition at line 1296 of file execMain.c.

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

References EState::es_instrument, EState::es_opened_result_relations, EState::es_query_cxt, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations,