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)
 
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, Datum *values, 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 ExecFreeExprContext (PlanState *planstate)
 
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, Datum *values, bool *isnull, EState *estate, bool newIndex)
 
bool RelationFindReplTupleByIndex (Relation rel, Oid idxoid, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
bool RelationFindReplTupleSeq (Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
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:182

Definition at line 521 of file executor.h.

◆ EvalPlanQualSetSlot

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

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

◆ GetPerTupleMemoryContext

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

Definition at line 554 of file executor.h.

◆ ResetExprContext

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

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 472 of file executor.h.

◆ ExecScanRecheckMtd

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

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

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

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

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

◆ BuildTupleHashTable()

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

Definition at line 255 of file execGrouping.c.

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

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

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

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,
Datum values,
bool isnull,
EState estate,
bool  newIndex 
)

Definition at line 910 of file execIndexing.c.

915 {
916  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
917  values, isnull,
918  estate, newIndex,
919  CEOUC_WAIT, false, NULL);
920 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool violationOK, ItemPointer conflictTid)
Definition: execIndexing.c:684
@ 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 620 of file execReplication.c.

621 {
622  PublicationDesc pubdesc;
623 
624  /*
625  * Skip checking the replica identity for partitioned tables, because the
626  * operations are actually performed on the leaf partitions.
627  */
628  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
629  return;
630 
631  /* We only need to do checks for UPDATE and DELETE. */
632  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
633  return;
634 
635  /*
636  * It is only safe to execute UPDATE/DELETE when all columns, referenced
637  * in the row filters from publications which the relation is in, are
638  * valid - i.e. when all referenced columns are part of REPLICA IDENTITY
639  * or the table does not publish UPDATEs or DELETEs.
640  *
641  * XXX We could optimize it by first checking whether any of the
642  * publications have a row filter for this relation. If not and relation
643  * has replica identity then we can avoid building the descriptor but as
644  * this happens only one time it doesn't seem worth the additional
645  * complexity.
646  */
647  RelationBuildPublicationDesc(rel, &pubdesc);
648  if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
649  ereport(ERROR,
650  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
651  errmsg("cannot update table \"%s\"",
653  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
654  else if (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
655  ereport(ERROR,
656  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
657  errmsg("cannot update table \"%s\"",
659  errdetail("Column list used by the publication does not cover the replica identity.")));
660  else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
661  ereport(ERROR,
662  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
663  errmsg("cannot delete from table \"%s\"",
665  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
666  else if (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
667  ereport(ERROR,
668  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
669  errmsg("cannot delete from table \"%s\"",
671  errdetail("Column list used by the publication does not cover the replica identity.")));
672 
673  /* If relation has replica identity we are always good. */
675  return;
676 
677  /* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */
678  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
679  return;
680 
681  /*
682  * This is UPDATE/DELETE and there is no replica identity.
683  *
684  * Check if the table publishes UPDATES or DELETES.
685  */
686  if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
687  ereport(ERROR,
688  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
689  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
691  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
692  else if (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
693  ereport(ERROR,
694  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
695  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
697  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
698 }
#define OidIsValid(objectId)
Definition: c.h:759
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
@ CMD_DELETE
Definition: nodes.h:279
@ CMD_UPDATE
Definition: nodes.h:277
#define RelationGetRelationName(relation)
Definition: rel.h:538
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Definition: relcache.c:5648
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4948
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 707 of file execReplication.c.

709 {
710  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
711  ereport(ERROR,
712  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
713  errmsg("cannot use relation \"%s.%s\" as logical replication target",
714  nspname, relname),
716 }
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 
)

Definition at line 1015 of file execMain.c.

1016 {
1017  Relation resultRel = resultRelInfo->ri_RelationDesc;
1018  TriggerDesc *trigDesc = resultRel->trigdesc;
1019  FdwRoutine *fdwroutine;
1020 
1021  switch (resultRel->rd_rel->relkind)
1022  {
1023  case RELKIND_RELATION:
1024  case RELKIND_PARTITIONED_TABLE:
1025  CheckCmdReplicaIdentity(resultRel, operation);
1026  break;
1027  case RELKIND_SEQUENCE:
1028  ereport(ERROR,
1029  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1030  errmsg("cannot change sequence \"%s\"",
1031  RelationGetRelationName(resultRel))));
1032  break;
1033  case RELKIND_TOASTVALUE:
1034  ereport(ERROR,
1035  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1036  errmsg("cannot change TOAST relation \"%s\"",
1037  RelationGetRelationName(resultRel))));
1038  break;
1039  case RELKIND_VIEW:
1040 
1041  /*
1042  * Okay only if there's a suitable INSTEAD OF trigger. Messages
1043  * here should match rewriteHandler.c's rewriteTargetView and
1044  * RewriteQuery, except that we omit errdetail because we haven't
1045  * got the information handy (and given that we really shouldn't
1046  * get here anyway, it's not worth great exertion to get).
1047  */
1048  switch (operation)
1049  {
1050  case CMD_INSERT:
1051  if (!trigDesc || !trigDesc->trig_insert_instead_row)
1052  ereport(ERROR,
1053  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1054  errmsg("cannot insert into view \"%s\"",
1055  RelationGetRelationName(resultRel)),
1056  errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
1057  break;
1058  case CMD_UPDATE:
1059  if (!trigDesc || !trigDesc->trig_update_instead_row)
1060  ereport(ERROR,
1061  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1062  errmsg("cannot update view \"%s\"",
1063  RelationGetRelationName(resultRel)),
1064  errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
1065  break;
1066  case CMD_DELETE:
1067  if (!trigDesc || !trigDesc->trig_delete_instead_row)
1068  ereport(ERROR,
1069  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1070  errmsg("cannot delete from view \"%s\"",
1071  RelationGetRelationName(resultRel)),
1072  errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
1073  break;
1074  default:
1075  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1076  break;
1077  }
1078  break;
1079  case RELKIND_MATVIEW:
1081  ereport(ERROR,
1082  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1083  errmsg("cannot change materialized view \"%s\"",
1084  RelationGetRelationName(resultRel))));
1085  break;
1086  case RELKIND_FOREIGN_TABLE:
1087  /* Okay only if the FDW supports it */
1088  fdwroutine = resultRelInfo->ri_FdwRoutine;
1089  switch (operation)
1090  {
1091  case CMD_INSERT:
1092  if (fdwroutine->ExecForeignInsert == NULL)
1093  ereport(ERROR,
1094  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1095  errmsg("cannot insert into foreign table \"%s\"",
1096  RelationGetRelationName(resultRel))));
1097  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1098  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1099  ereport(ERROR,
1100  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1101  errmsg("foreign table \"%s\" does not allow inserts",
1102  RelationGetRelationName(resultRel))));
1103  break;
1104  case CMD_UPDATE:
1105  if (fdwroutine->ExecForeignUpdate == NULL)
1106  ereport(ERROR,
1107  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1108  errmsg("cannot update foreign table \"%s\"",
1109  RelationGetRelationName(resultRel))));
1110  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1111  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1112  ereport(ERROR,
1113  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1114  errmsg("foreign table \"%s\" does not allow updates",
1115  RelationGetRelationName(resultRel))));
1116  break;
1117  case CMD_DELETE:
1118  if (fdwroutine->ExecForeignDelete == NULL)
1119  ereport(ERROR,
1120  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1121  errmsg("cannot delete from foreign table \"%s\"",
1122  RelationGetRelationName(resultRel))));
1123  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1124  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1125  ereport(ERROR,
1126  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1127  errmsg("foreign table \"%s\" does not allow deletes",
1128  RelationGetRelationName(resultRel))));
1129  break;
1130  default:
1131  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1132  break;
1133  }
1134  break;
1135  default:
1136  ereport(ERROR,
1137  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1138  errmsg("cannot change relation \"%s\"",
1139  RelationGetRelationName(resultRel))));
1140  break;
1141  }
1142 }
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition: matview.c:918
@ CMD_INSERT
Definition: nodes.h:278
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
TriggerDesc * trigdesc
Definition: rel.h:117
Relation ri_RelationDesc
Definition: execnodes.h:450
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:497
bool trig_update_instead_row
Definition: reltrigger.h:63
bool trig_delete_instead_row
Definition: reltrigger.h:68
bool trig_insert_instead_row
Definition: reltrigger.h:58

References CheckCmdReplicaIdentity(), CMD_DELETE, CMD_INSERT, CMD_UPDATE, elog(), ereport, errcode(), errhint(), errmsg(), ERROR, FdwRoutine::ExecForeignDelete, FdwRoutine::ExecForeignInsert, FdwRoutine::ExecForeignUpdate, FdwRoutine::IsForeignRelUpdatable, MatViewIncrementalMaintenanceIsEnabled(), RelationData::rd_rel, RelationGetRelationName, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_RelationDesc, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, and RelationData::trigdesc.

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

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 93 of file execUtils.c.

94 {
95  EState *estate;
96  MemoryContext qcontext;
97  MemoryContext oldcontext;
98 
99  /*
100  * Create the per-query context for this Executor run.
101  */
103  "ExecutorState",
105 
106  /*
107  * Make the EState node within the per-query context. This way, we don't
108  * need a separate pfree() operation for it at shutdown.
109  */
110  oldcontext = MemoryContextSwitchTo(qcontext);
111 
112  estate = makeNode(EState);
113 
114  /*
115  * Initialize all fields of the Executor State structure
116  */
118  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
119  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
120  estate->es_range_table = NIL;
121  estate->es_range_table_size = 0;
122  estate->es_relations = NULL;
123  estate->es_rowmarks = NULL;
124  estate->es_rteperminfos = NIL;
125  estate->es_plannedstmt = NULL;
126 
127  estate->es_junkFilter = NULL;
128 
129  estate->es_output_cid = (CommandId) 0;
130 
131  estate->es_result_relations = NULL;
134  estate->es_trig_target_relations = NIL;
135 
138 
139  estate->es_param_list_info = NULL;
140  estate->es_param_exec_vals = NULL;
141 
142  estate->es_queryEnv = NULL;
143 
144  estate->es_query_cxt = qcontext;
145 
146  estate->es_tupleTable = NIL;
147 
148  estate->es_processed = 0;
149  estate->es_total_processed = 0;
150 
151  estate->es_top_eflags = 0;
152  estate->es_instrument = 0;
153  estate->es_finished = false;
154 
155  estate->es_exprcontexts = NIL;
156 
157  estate->es_subplanstates = NIL;
158 
159  estate->es_auxmodifytables = NIL;
160 
161  estate->es_per_tuple_exprcontext = NULL;
162 
163  estate->es_sourceText = NULL;
164 
165  estate->es_use_parallel_mode = false;
166 
167  estate->es_jit_flags = 0;
168  estate->es_jit = NULL;
169 
170  /*
171  * Return the executor state structure
172  */
173  MemoryContextSwitchTo(oldcontext);
174 
175  return estate;
176 }
uint32 CommandId
Definition: c.h:650
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define makeNode(_type_)
Definition: nodes.h:176
#define NIL
Definition: pg_list.h:68
@ ForwardScanDirection
Definition: sdir.h:28
#define InvalidSnapshot
Definition: snapshot.h:123
uint64 es_processed
Definition: execnodes.h:663
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:622
List * es_tuple_routing_result_relations
Definition: execnodes.h:647
int es_top_eflags
Definition: execnodes.h:668
struct JitContext * es_jit
Definition: execnodes.h:708
int es_instrument
Definition: execnodes.h:669
PlannedStmt * es_plannedstmt
Definition: execnodes.h:625
QueryEnvironment * es_queryEnv
Definition: execnodes.h:656
ResultRelInfo ** es_result_relations
Definition: execnodes.h:634
ParamExecData * es_param_exec_vals
Definition: execnodes.h:654
uint64 es_total_processed
Definition: execnodes.h:665
List * es_range_table
Definition: execnodes.h:618
List * es_rteperminfos
Definition: execnodes.h:624
List * es_exprcontexts
Definition: execnodes.h:672
ParamListInfo es_param_list_info
Definition: execnodes.h:653
bool es_finished
Definition: execnodes.h:670
List * es_insert_pending_result_relations
Definition: execnodes.h:715
MemoryContext es_query_cxt
Definition: execnodes.h:659
List * es_tupleTable
Definition: execnodes.h:661
ScanDirection es_direction
Definition: execnodes.h:615
List * es_trig_target_relations
Definition: execnodes.h:650
int es_jit_flags
Definition: execnodes.h:707
List * es_opened_result_relations
Definition: execnodes.h:637
bool es_use_parallel_mode
Definition: execnodes.h:693
Relation * es_relations
Definition: execnodes.h:620
List * es_subplanstates
Definition: execnodes.h:674
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:683
CommandId es_output_cid
Definition: execnodes.h:631
Index es_range_table_size
Definition: execnodes.h:619
List * es_insert_pending_modifytables
Definition: execnodes.h:716
const char * es_sourceText
Definition: execnodes.h:626
Snapshot es_snapshot
Definition: execnodes.h:616
List * es_auxmodifytables
Definition: execnodes.h:676
JunkFilter * es_junkFilter
Definition: execnodes.h:628
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:617

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

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

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 309 of file execUtils.c.

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

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 360 of file execUtils.c.

361 {
362  ExprContext *econtext;
363 
364  /* Create the ExprContext node within the caller's memory context */
365  econtext = makeNode(ExprContext);
366 
367  /* Initialize fields of ExprContext */
368  econtext->ecxt_scantuple = NULL;
369  econtext->ecxt_innertuple = NULL;
370  econtext->ecxt_outertuple = NULL;
371 
373 
374  /*
375  * Create working memory for expression evaluation in this context.
376  */
377  econtext->ecxt_per_tuple_memory =
379  "ExprContext",
381 
382  econtext->ecxt_param_exec_vals = NULL;
383  econtext->ecxt_param_list_info = NULL;
384 
385  econtext->ecxt_aggvalues = NULL;
386  econtext->ecxt_aggnulls = NULL;
387 
388  econtext->caseValue_datum = (Datum) 0;
389  econtext->caseValue_isNull = true;
390 
391  econtext->domainValue_datum = (Datum) 0;
392  econtext->domainValue_isNull = true;
393 
394  econtext->ecxt_estate = NULL;
395 
396  econtext->ecxt_callbacks = NULL;
397 
398  return econtext;
399 }
uintptr_t Datum
Definition: postgres.h:64
Datum domainValue_datum
Definition: execnodes.h:280
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:261
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:257
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:251
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:260
Datum * ecxt_aggvalues
Definition: execnodes.h:268
bool caseValue_isNull
Definition: execnodes.h:276
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:249
Datum caseValue_datum
Definition: execnodes.h:274
bool * ecxt_aggnulls
Definition: execnodes.h:270
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:256
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:288
bool domainValue_isNull
Definition: execnodes.h:282
struct EState * ecxt_estate
Definition: execnodes.h:285
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:253

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

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

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

Referenced by ExecInitAgg().

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 2304 of file execTuples.c.

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

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,
Datum values,
bool isnull 
)

Definition at line 2276 of file execTuples.c.

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

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

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

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 2334 of file execTuples.c.

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

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

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

◆ EvalPlanQual()

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

Definition at line 2485 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2766 of file execMain.c.

2767 {
2768  EState *parentestate = epqstate->parentestate;
2769  EState *recheckestate = epqstate->recheckestate;
2770 
2771  if (recheckestate == NULL)
2772  {
2773  /* First time through, so create a child EState */
2774  EvalPlanQualStart(epqstate, epqstate->plan);
2775  }
2776  else
2777  {
2778  /*
2779  * We already have a suitable child EPQ tree, so just reset it.
2780  */
2781  Index rtsize = parentestate->es_range_table_size;
2782  PlanState *rcplanstate = epqstate->recheckplanstate;
2783 
2784  /*
2785  * Reset the relsubs_done[] flags to equal relsubs_blocked[], so that
2786  * the EPQ run will never attempt to fetch tuples from blocked target
2787  * relations.
2788  */
2789  memcpy(epqstate->relsubs_done, epqstate->relsubs_blocked,
2790  rtsize * sizeof(bool));
2791 
2792  /* Recopy current values of parent parameters */
2793  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2794  {
2795  int i;
2796 
2797  /*
2798  * Force evaluation of any InitPlan outputs that could be needed
2799  * by the subplan, just in case they got reset since
2800  * EvalPlanQualStart (see comments therein).
2801  */
2802  ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2803  GetPerTupleExprContext(parentestate));
2804 
2805  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2806 
2807  while (--i >= 0)
2808  {
2809  /* copy value if any, but not execPlan link */
2810  recheckestate->es_param_exec_vals[i].value =
2811  parentestate->es_param_exec_vals[i].value;
2812  recheckestate->es_param_exec_vals[i].isnull =
2813  parentestate->es_param_exec_vals[i].isnull;
2814  }
2815  }
2816 
2817  /*
2818  * Mark child plan tree as needing rescan at all scan nodes. The
2819  * first ExecProcNode will take care of actually doing the rescan.
2820  */
2821  rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2822  epqstate->epqParam);
2823  }
2824 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:755
unsigned int Index
Definition: c.h:598
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition: execMain.c:2833
#define GetPerTupleExprContext(estate)
Definition: executor.h:549
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:1191
int epqParam
Definition: execnodes.h:1174
EState * parentestate
Definition: execnodes.h:1173
EState * recheckestate
Definition: execnodes.h:1205
PlanState * recheckplanstate
Definition: execnodes.h:1230
bool isnull
Definition: params.h:150
Datum value
Definition: params.h:149
Plan * plan
Definition: execnodes.h:1037
Bitmapset * chgParam
Definition: execnodes.h:1069
Bitmapset * extParam
Definition: plannodes.h:171
List * paramExecTypes
Definition: plannodes.h:94

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

2998 {
2999  EState *estate = epqstate->recheckestate;
3000  Index rtsize;
3001  MemoryContext oldcontext;
3002  ListCell *l;
3003 
3004  rtsize = epqstate->parentestate->es_range_table_size;
3005 
3006  /*
3007  * We may have a tuple table, even if EPQ wasn't started, because we allow
3008  * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
3009  */
3010  if (epqstate->tuple_table != NIL)
3011  {
3012  memset(epqstate->relsubs_slot, 0,
3013  rtsize * sizeof(TupleTableSlot *));
3014  ExecResetTupleTable(epqstate->tuple_table, true);
3015  epqstate->tuple_table = NIL;
3016  }
3017 
3018  /* EPQ wasn't started, nothing further to do */
3019  if (estate == NULL)
3020  return;
3021 
3022  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3023 
3024  ExecEndNode(epqstate->recheckplanstate);
3025 
3026  foreach(l, estate->es_subplanstates)
3027  {
3028  PlanState *subplanstate = (PlanState *) lfirst(l);
3029 
3030  ExecEndNode(subplanstate);
3031  }
3032 
3033  /* throw away the per-estate tuple table, some node may have used it */
3034  ExecResetTupleTable(estate->es_tupleTable, false);
3035 
3036  /* Close any result and trigger target relations attached to this EState */
3037  ExecCloseResultRelations(estate);
3038 
3039  MemoryContextSwitchTo(oldcontext);
3040 
3041  FreeExecutorState(estate);
3042 
3043  /* Mark EPQState idle */
3044  epqstate->origslot = NULL;
3045  epqstate->recheckestate = NULL;
3046  epqstate->recheckplanstate = NULL;
3047  epqstate->relsubs_rowmark = NULL;
3048  epqstate->relsubs_done = NULL;
3049  epqstate->relsubs_blocked = NULL;
3050 }
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1532
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1192
void FreeExecutorState(EState *estate)
Definition: execUtils.c:194
#define lfirst(lc)
Definition: pg_list.h:172
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1212
TupleTableSlot * origslot
Definition: execnodes.h:1200
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1184
List * tuple_table
Definition: execnodes.h:1183

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

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

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

2557 {
2558  Index rtsize = parentestate->es_range_table_size;
2559 
2560  /* initialize data not changing over EPQState's lifetime */
2561  epqstate->parentestate = parentestate;
2562  epqstate->epqParam = epqParam;
2563  epqstate->resultRelations = resultRelations;
2564 
2565  /*
2566  * Allocate space to reference a slot for each potential rti - do so now
2567  * rather than in EvalPlanQualBegin(), as done for other dynamically
2568  * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2569  * that *may* need EPQ later, without forcing the overhead of
2570  * EvalPlanQualBegin().
2571  */
2572  epqstate->tuple_table = NIL;
2573  epqstate->relsubs_slot = (TupleTableSlot **)
2574  palloc0(rtsize * sizeof(TupleTableSlot *));
2575 
2576  /* ... and remember data that EvalPlanQualBegin will need */
2577  epqstate->plan = subplan;
2578  epqstate->arowMarks = auxrowmarks;
2579 
2580  /* ... and mark the EPQ state inactive */
2581  epqstate->origslot = NULL;
2582  epqstate->recheckestate = NULL;
2583  epqstate->recheckplanstate = NULL;
2584  epqstate->relsubs_rowmark = NULL;
2585  epqstate->relsubs_done = NULL;
2586  epqstate->relsubs_blocked = NULL;
2587 }
void * palloc0(Size size)
Definition: mcxt.c:1257
List * resultRelations
Definition: execnodes.h:1175
List * arowMarks
Definition: execnodes.h:1192

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

2751 {
2752  MemoryContext oldcontext;
2753  TupleTableSlot *slot;
2754 
2755  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2756  slot = ExecProcNode(epqstate->recheckplanstate);
2757  MemoryContextSwitchTo(oldcontext);
2758 
2759  return slot;
2760 }
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:268

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

2597 {
2598  /* If we have a live EPQ query, shut it down */
2599  EvalPlanQualEnd(epqstate);
2600  /* And set/change the plan pointer */
2601  epqstate->plan = subplan;
2602  /* The rowmarks depend on the plan, too */
2603  epqstate->arowMarks = auxrowmarks;
2604 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2997

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2613 of file execMain.c.

2615 {
2616  TupleTableSlot **slot;
2617 
2618  Assert(relation);
2619  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2620  slot = &epqstate->relsubs_slot[rti - 1];
2621 
2622  if (*slot == NULL)
2623  {
2624  MemoryContext oldcontext;
2625 
2626  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2627  *slot = table_slot_create(relation, &epqstate->tuple_table);
2628  MemoryContextSwitchTo(oldcontext);
2629  }
2630 
2631  return *slot;
2632 }
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 543 of file execUtils.c.

545 {
546  planstate->ps_ProjInfo =
548  planstate->ps_ExprContext,
549  planstate->ps_ResultTupleSlot,
550  planstate,
551  inputDesc);
552 }
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:357
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1075
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1077
List * targetlist
Definition: plannodes.h:153

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

679 {
680  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
681 
682  ExecSetSlotDescriptor(slot, tupDesc);
683 }
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:1290

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

2416 {
2417  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2418  char resname[32];
2419 
2420  aerm->rowmark = erm;
2421 
2422  /* Look up the resjunk columns associated with this rowmark */
2423  if (erm->markType != ROW_MARK_COPY)
2424  {
2425  /* need ctid for all methods other than COPY */
2426  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2427  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2428  resname);
2429  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2430  elog(ERROR, "could not find junk %s column", resname);
2431  }
2432  else
2433  {
2434  /* need wholerow if COPY */
2435  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2436  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2437  resname);
2438  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2439  elog(ERROR, "could not find junk %s column", resname);
2440  }
2441 
2442  /* if child rel, need tableoid */
2443  if (erm->rti != erm->prti)
2444  {
2445  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2446  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2447  resname);
2448  if (!AttributeNumberIsValid(aerm->toidAttNo))
2449  elog(ERROR, "could not find junk %s column", resname);
2450  }
2451 
2452  return aerm;
2453 }
#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:745

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

3897 {
3899  ExprEvalStep scratch = {0};
3900  int maxatt = -1;
3901  List *adjust_jumps = NIL;
3902  ListCell *lc;
3903 
3904  /*
3905  * When no columns are actually compared, the result's always true. See
3906  * special case in ExecQual().
3907  */
3908  if (numCols == 0)
3909  return NULL;
3910 
3911  state->expr = NULL;
3912  state->flags = EEO_FLAG_IS_QUAL;
3913  state->parent = parent;
3914 
3915  scratch.resvalue = &state->resvalue;
3916  scratch.resnull = &state->resnull;
3917 
3918  /* compute max needed attribute */
3919  for (int natt = 0; natt < numCols; natt++)
3920  {
3921  int attno = keyColIdx[natt];
3922 
3923  if (attno > maxatt)
3924  maxatt = attno;
3925  }
3926  Assert(maxatt >= 0);
3927 
3928  /* push deform steps */
3929  scratch.opcode = EEOP_INNER_FETCHSOME;
3930  scratch.d.fetch.last_var = maxatt;
3931  scratch.d.fetch.fixed = false;
3932  scratch.d.fetch.known_desc = ldesc;
3933  scratch.d.fetch.kind = lops;
3934  if (ExecComputeSlotInfo(state, &scratch))
3935  ExprEvalPushStep(state, &scratch);
3936 
3937  scratch.opcode = EEOP_OUTER_FETCHSOME;
3938  scratch.d.fetch.last_var = maxatt;
3939  scratch.d.fetch.fixed = false;
3940  scratch.d.fetch.known_desc = rdesc;
3941  scratch.d.fetch.kind = rops;
3942  if (ExecComputeSlotInfo(state, &scratch))
3943  ExprEvalPushStep(state, &scratch);
3944 
3945  /*
3946  * Start comparing at the last field (least significant sort key). That's
3947  * the most likely to be different if we are dealing with sorted input.
3948  */
3949  for (int natt = numCols; --natt >= 0;)
3950  {
3951  int attno = keyColIdx[natt];
3952  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3953  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3954  Oid foid = eqfunctions[natt];
3955  Oid collid = collations[natt];
3956  FmgrInfo *finfo;
3957  FunctionCallInfo fcinfo;
3958  AclResult aclresult;
3959 
3960  /* Check permission to call function */
3961  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
3962  if (aclresult != ACLCHECK_OK)
3963  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3964 
3966 
3967  /* Set up the primary fmgr lookup information */
3968  finfo = palloc0(sizeof(FmgrInfo));
3969  fcinfo = palloc0(SizeForFunctionCallInfo(2));
3970  fmgr_info(foid, finfo);
3971  fmgr_info_set_expr(NULL, finfo);
3972  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3973  collid, NULL, NULL);
3974 
3975  /* left arg */
3976  scratch.opcode = EEOP_INNER_VAR;
3977  scratch.d.var.attnum = attno - 1;
3978  scratch.d.var.vartype = latt->atttypid;
3979  scratch.resvalue = &fcinfo->args[0].value;
3980  scratch.resnull = &fcinfo->args[0].isnull;
3981  ExprEvalPushStep(state, &scratch);
3982 
3983  /* right arg */
3984  scratch.opcode = EEOP_OUTER_VAR;
3985  scratch.d.var.attnum = attno - 1;
3986  scratch.d.var.vartype = ratt->atttypid;
3987  scratch.resvalue = &fcinfo->args[1].value;
3988  scratch.resnull = &fcinfo->args[1].isnull;
3989  ExprEvalPushStep(state, &scratch);
3990 
3991  /* evaluate distinctness */
3992  scratch.opcode = EEOP_NOT_DISTINCT;
3993  scratch.d.func.finfo = finfo;
3994  scratch.d.func.fcinfo_data = fcinfo;
3995  scratch.d.func.fn_addr = finfo->fn_addr;
3996  scratch.d.func.nargs = 2;
3997  scratch.resvalue = &state->resvalue;
3998  scratch.resnull = &state->resnull;
3999  ExprEvalPushStep(state, &scratch);
4000 
4001  /* then emit EEOP_QUAL to detect if result is false (or null) */
4002  scratch.opcode = EEOP_QUAL;
4003  scratch.d.qualexpr.jumpdone = -1;
4004  scratch.resvalue = &state->resvalue;
4005  scratch.resnull = &state->resnull;
4006  ExprEvalPushStep(state, &scratch);
4007  adjust_jumps = lappend_int(adjust_jumps,
4008  state->steps_len - 1);
4009  }
4010 
4011  /* adjust jump targets */
4012  foreach(lc, adjust_jumps)
4013  {
4014  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4015 
4016  Assert(as->opcode == EEOP_QUAL);
4017  Assert(as->d.qualexpr.jumpdone == -1);
4018  as->d.qualexpr.jumpdone = state->steps_len;
4019  }
4020 
4021  scratch.resvalue = NULL;
4022  scratch.resnull = NULL;
4023  scratch.opcode = EEOP_DONE;
4024  ExprEvalPushStep(state, &scratch);
4025 
4027 
4028  return state;
4029 }
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2673
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3775
Oid collid
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2536
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2830
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:872
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:172
@ EEOP_INNER_VAR
Definition: execExpr.h:76
@ EEOP_DONE
Definition: execExpr.h:68
@ EEOP_QUAL
Definition: execExpr.h:134
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:71
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:72
@ EEOP_OUTER_VAR
Definition: execExpr.h:77
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:75
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:356
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1590
Oid GetUserId(void)
Definition: miscinit.c:510
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
@ OBJECT_FUNCTION
Definition: parsenodes.h:2101
#define ACL_EXECUTE
Definition: parsenodes.h:90
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define lfirst_int(lc)
Definition: pg_list.h:173
struct ExprEvalStep::@50::@51 fetch
struct ExprEvalStep::@50::@52 var
intptr_t opcode
Definition: execExpr.h:275
Datum * resvalue
Definition: execExpr.h:278
struct ExprEvalStep::@50::@59 qualexpr
struct ExprEvalStep::@50::@57 func
union ExprEvalStep::@50 d
bool * resnull
Definition: execExpr.h:279
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 4047 of file execExpr.c.

4054 {
4056  ExprEvalStep scratch = {0};
4057  int maxatt = list_length(param_exprs);
4058  List *adjust_jumps = NIL;
4059  ListCell *lc;
4060 
4061  state->expr = NULL;
4062  state->flags = EEO_FLAG_IS_QUAL;
4063  state->parent = parent;
4064 
4065  scratch.resvalue = &state->resvalue;
4066  scratch.resnull = &state->resnull;
4067 
4068  /* push deform steps */
4069  scratch.opcode = EEOP_INNER_FETCHSOME;
4070  scratch.d.fetch.last_var = maxatt;
4071  scratch.d.fetch.fixed = false;
4072  scratch.d.fetch.known_desc = desc;
4073  scratch.d.fetch.kind = lops;
4074  if (ExecComputeSlotInfo(state, &scratch))
4075  ExprEvalPushStep(state, &scratch);
4076 
4077  scratch.opcode = EEOP_OUTER_FETCHSOME;
4078  scratch.d.fetch.last_var = maxatt;
4079  scratch.d.fetch.fixed = false;
4080  scratch.d.fetch.known_desc = desc;
4081  scratch.d.fetch.kind = rops;
4082  if (ExecComputeSlotInfo(state, &scratch))
4083  ExprEvalPushStep(state, &scratch);
4084 
4085  for (int attno = 0; attno < maxatt; attno++)
4086  {
4087  Form_pg_attribute att = TupleDescAttr(desc, attno);
4088  Oid foid = eqfunctions[attno];
4089  Oid collid = collations[attno];
4090  FmgrInfo *finfo;
4091  FunctionCallInfo fcinfo;
4092  AclResult aclresult;
4093 
4094  /* Check permission to call function */
4095  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4096  if (aclresult != ACLCHECK_OK)
4097  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4098 
4100 
4101  /* Set up the primary fmgr lookup information */
4102  finfo = palloc0(sizeof(FmgrInfo));
4103  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4104  fmgr_info(foid, finfo);
4105  fmgr_info_set_expr(NULL, finfo);
4106  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4107  collid, NULL, NULL);
4108 
4109  /* left arg */
4110  scratch.opcode = EEOP_INNER_VAR;
4111  scratch.d.var.attnum = attno;
4112  scratch.d.var.vartype = att->atttypid;
4113  scratch.resvalue = &fcinfo->args[0].value;
4114  scratch.resnull = &fcinfo->args[0].isnull;
4115  ExprEvalPushStep(state, &scratch);
4116 
4117  /* right arg */
4118  scratch.opcode = EEOP_OUTER_VAR;
4119  scratch.d.var.attnum = attno;
4120  scratch.d.var.vartype = att->atttypid;
4121  scratch.resvalue = &fcinfo->args[1].value;
4122  scratch.resnull = &fcinfo->args[1].isnull;
4123  ExprEvalPushStep(state, &scratch);
4124 
4125  /* evaluate distinctness */
4126  scratch.opcode = EEOP_NOT_DISTINCT;
4127  scratch.d.func.finfo = finfo;
4128  scratch.d.func.fcinfo_data = fcinfo;
4129  scratch.d.func.fn_addr = finfo->fn_addr;
4130  scratch.d.func.nargs = 2;
4131  scratch.resvalue = &state->resvalue;
4132  scratch.resnull = &state->resnull;
4133  ExprEvalPushStep(state, &scratch);
4134 
4135  /* then emit EEOP_QUAL to detect if result is false (or null) */
4136  scratch.opcode = EEOP_QUAL;
4137  scratch.d.qualexpr.jumpdone = -1;
4138  scratch.resvalue = &state->resvalue;
4139  scratch.resnull = &state->resnull;
4140  ExprEvalPushStep(state, &scratch);
4141  adjust_jumps = lappend_int(adjust_jumps,
4142  state->steps_len - 1);
4143  }
4144 
4145  /* adjust jump targets */
4146  foreach(lc, adjust_jumps)
4147  {
4148  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4149 
4150  Assert(as->opcode == EEOP_QUAL);
4151  Assert(as->d.qualexpr.jumpdone == -1);
4152  as->d.qualexpr.jumpdone = state->steps_len;
4153  }
4154 
4155  scratch.resvalue = NULL;
4156  scratch.resnull = NULL;
4157  scratch.opcode = EEOP_DONE;
4158  ExprEvalPushStep(state, &scratch);
4159 
4161 
4162  return state;
4163 }

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

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

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

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

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

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)

Definition at line 842 of file execExpr.c.

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

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

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

◆ ExecCheckIndexConstraints()

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

Definition at line 522 of file execIndexing.c.

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

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

583 {
584  ListCell *l;
585  bool result = true;
586 
587 #ifdef USE_ASSERT_CHECKING
588  Bitmapset *indexset = NULL;
589 
590  /* Check that rteperminfos is consistent with rangeTable */
591  foreach(l, rangeTable)
592  {
594 
595  if (rte->perminfoindex != 0)
596  {
597  /* Sanity checks */
598  (void) getRTEPermissionInfo(rteperminfos, rte);
599  /* Many-to-one mapping not allowed */
600  Assert(!bms_is_member(rte->perminfoindex, indexset));
601  indexset = bms_add_member(indexset, rte->perminfoindex);
602  }
603  }
604 
605  /* All rteperminfos are referenced */
606  Assert(bms_num_members(indexset) == list_length(rteperminfos));
607 #endif
608 
609  foreach(l, rteperminfos)
610  {
612 
613  Assert(OidIsValid(perminfo->relid));
614  result = ExecCheckOneRelPerms(perminfo);
615  if (!result)
616  {
617  if (ereport_on_violation)
620  get_rel_name(perminfo->relid));
621  return false;
622  }
623  }
624 
626  result = (*ExecutorCheckPerms_hook) (rangeTable, rteperminfos,
627  ereport_on_violation);
628  return result;
629 }
@ ACLCHECK_NO_PRIV
Definition: acl.h:184
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:665
static bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
Definition: execMain.c:636
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:79
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1985
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1910
ObjectType get_relkind_objtype(char relkind)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
Index perminfoindex
Definition: parsenodes.h:1076

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

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1150 of file execUtils.c.

1151 {
1152  int len = 0;
1153  ListCell *tl;
1154 
1155  foreach(tl, targetlist)
1156  {
1157  TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1158 
1159  if (!curTle->resjunk)
1160  len++;
1161  }
1162  return len;
1163 }

References len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 1951 of file execTuples.c.

1952 {
1953  return ExecTypeFromTLInternal(targetList, true);
1954 }
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
Definition: execTuples.c:1957

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 
237  numIndices = resultRelInfo->ri_NumIndices;
238  indexDescs = resultRelInfo->ri_IndexRelationDescs;
239 
240  for (i = 0; i < numIndices; i++)
241  {
242  if (indexDescs[i] == NULL)
243  continue; /* shouldn't happen? */
244 
245  /* Drop lock acquired by ExecOpenIndices */
246  index_close(indexDescs[i], RowExclusiveLock);
247  }
248 
249  /*
250  * XXX should free indexInfo array here too? Currently we assume that
251  * such stuff will be cleaned up automatically in FreeExecutorState.
252  */
253 }
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
#define RowExclusiveLock
Definition: lockdefs.h:38

References i, index_close(), ResultRelInfo::ri_IndexRelationDescs, 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 1592 of file execMain.c.

1593 {
1594  int i;
1595 
1596  for (i = 0; i < estate->es_range_table_size; i++)
1597  {
1598  if (estate->es_relations[i])
1599  table_close(estate->es_relations[i], NoLock);
1600  }
1601 }
#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 1532 of file execMain.c.

1533 {
1534  ListCell *l;
1535 
1536  /*
1537  * close indexes of result relation(s) if any. (Rels themselves are
1538  * closed in ExecCloseRangeTableRelations())
1539  *
1540  * In addition, close the stub RTs that may be in each resultrel's
1541  * ri_ancestorResultRels.
1542  */
1543  foreach(l, estate->es_opened_result_relations)
1544  {
1545  ResultRelInfo *resultRelInfo = lfirst(l);
1546  ListCell *lc;
1547 
1548  ExecCloseIndices(resultRelInfo);
1549  foreach(lc, resultRelInfo->ri_ancestorResultRels)
1550  {
1551  ResultRelInfo *rInfo = lfirst(lc);
1552 
1553  /*
1554  * Ancestors with RTI > 0 (should only be the root ancestor) are
1555  * closed by ExecCloseRangeTableRelations.
1556  */
1557  if (rInfo->ri_RangeTableIndex > 0)
1558  continue;
1559 
1561  }
1562  }
1563 
1564  /* Close any relations that have been opened by ExecGetTriggerResultRel(). */
1565  foreach(l, estate->es_trig_target_relations)
1566  {
1567  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1568 
1569  /*
1570  * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we
1571  * might be issuing a duplicate close against a Relation opened by
1572  * ExecGetRangeTableRelation.
1573  */
1574  Assert(resultRelInfo->ri_RangeTableIndex == 0);
1575 
1576  /*
1577  * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for
1578  * these rels, we needn't call ExecCloseIndices either.
1579  */
1580  Assert(resultRelInfo->ri_NumIndices == 0);
1581 
1582  table_close(resultRelInfo->ri_RelationDesc, NoLock);
1583  }
1584 }
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:231
Index ri_RangeTableIndex
Definition: execnodes.h:447
List * ri_ancestorResultRels
Definition: execnodes.h:584

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

565 {
566  if (tlist_matches_tupdesc(planstate,
567  planstate->plan->targetlist,
568  varno,
569  inputDesc))
570  {
571  planstate->ps_ProjInfo = NULL;
572  planstate->resultopsset = planstate->scanopsset;
573  planstate->resultopsfixed = planstate->scanopsfixed;
574  planstate->resultops = planstate->scanops;
575  }
576  else
577  {
578  if (!planstate->ps_ResultTupleSlot)
579  {
580  ExecInitResultSlot(planstate, &TTSOpsVirtual);
581  planstate->resultops = &TTSOpsVirtual;
582  planstate->resultopsfixed = true;
583  planstate->resultopsset = true;
584  }
585  ExecAssignProjectionInfo(planstate, inputDesc);
586  }
587 }
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1780
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
Definition: execUtils.c:590
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:543
const TupleTableSlotOps * resultops
Definition: execnodes.h:1114
bool resultopsset
Definition: execnodes.h:1122
const TupleTableSlotOps * scanops
Definition: execnodes.h:1111
bool scanopsset
Definition: execnodes.h:1119
bool scanopsfixed
Definition: execnodes.h:1115
bool resultopsfixed
Definition: execnodes.h:1118

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

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

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

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

◆ ExecCreateScanSlotFromOuterPlan()

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

Definition at line 690 of file execUtils.c.

693 {
695  TupleDesc tupDesc;
696 
697  outerPlan = outerPlanState(scanstate);
698  tupDesc = ExecGetResultType(outerPlan);
699 
700  ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
701 }
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1812
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:498
#define outerPlanState(node)
Definition: execnodes.h:1133
#define outerPlan(node)
Definition: plannodes.h:183

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:131
char * cursor_name
Definition: primnodes.h:1794
ItemPointerData curCtid
Definition: execnodes.h:750
ItemPointerData xs_heaptid
Definition: relscan.h:147
QueryDesc * queryDesc
Definition: portal.h:157
bool atEnd
Definition: portal.h:200
bool atStart
Definition: portal.h:199
PortalStrategy strategy
Definition: portal.h:146
EState * estate
Definition: execdesc.h:48
PlanState * planstate
Definition: execdesc.h:49
#define TableOidAttributeNumber
Definition: sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:410

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

Referenced by TidListEval().

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 557 of file execProcnode.c.

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

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

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

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

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

◆ ExecFilterJunk()

TupleTableSlot* ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 247 of file execJunk.c.

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

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

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

◆ ExecFindJunkAttribute()

AttrNumber ExecFindJunkAttribute ( JunkFilter junkfilter,
const char *  attrName 
)

Definition at line 210 of file execJunk.c.

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

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

2393 {
2394  if (rti > 0 && rti <= estate->es_range_table_size &&
2395  estate->es_rowmarks != NULL)
2396  {
2397  ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2398 
2399  if (erm)
2400  return erm;
2401  }
2402  if (!missing_ok)
2403  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2404  return NULL;
2405 }

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecFreeExprContext()

◆ ExecGetAllUpdatedCols()

Bitmapset* ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1350 of file execUtils.c.

1351 {
1352  return bms_union(ExecGetUpdatedCols(relinfo, estate),
1353  ExecGetExtraUpdatedCols(relinfo, estate));
1354 }
Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1340

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

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

◆ ExecGetAncestorResultRels()

List* ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1387 of file execMain.c.

1388 {
1389  ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1390  Relation partRel = resultRelInfo->ri_RelationDesc;
1391  Oid rootRelOid;
1392 
1393  if (!partRel->rd_rel->relispartition)
1394  elog(ERROR, "cannot find ancestors of a non-partition result relation");
1395  Assert(rootRelInfo != NULL);
1396  rootRelOid = RelationGetRelid(rootRelInfo->ri_RelationDesc);
1397  if (resultRelInfo->ri_ancestorResultRels == NIL)
1398  {
1399  ListCell *lc;
1400  List *oids = get_partition_ancestors(RelationGetRelid(partRel));
1401  List *ancResultRels = NIL;
1402 
1403  foreach(lc, oids)
1404  {
1405  Oid ancOid = lfirst_oid(lc);
1406  Relation ancRel;
1407  ResultRelInfo *rInfo;
1408 
1409  /*
1410  * Ignore the root ancestor here, and use ri_RootResultRelInfo
1411  * (below) for it instead. Also, we stop climbing up the
1412  * hierarchy when we find the table that was mentioned in the
1413  * query.
1414  */
1415  if (ancOid == rootRelOid)
1416  break;
1417 
1418  /*
1419  * All ancestors up to the root target relation must have been
1420  * locked by the planner or AcquireExecutorLocks().
1421  */
1422  ancRel = table_open(ancOid, NoLock);
1423  rInfo = makeNode(ResultRelInfo);
1424 
1425  /* dummy rangetable index */
1426  InitResultRelInfo(rInfo, ancRel, 0, NULL,
1427  estate->es_instrument);
1428  ancResultRels = lappend(ancResultRels, rInfo);
1429  }
1430  ancResultRels = lappend(ancResultRels, rootRelInfo);
1431  resultRelInfo->ri_ancestorResultRels = ancResultRels;
1432  }
1433 
1434  /* We must have found some ancestor */
1435  Assert(resultRelInfo->ri_ancestorResultRels != NIL);
1436 
1437  return resultRelInfo->ri_ancestorResultRels;
1438 }
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, ResultRelInfo *partition_root_rri, int instrument_options)
Definition: execMain.c:1216
List * lappend(List *list, void *datum)
Definition: list.c:338
List * get_partition_ancestors(Oid relid)
Definition: partition.c:133
#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 1237 of file execUtils.c.

1238 {
1239  /* If we didn't already do so, compute the map for this child. */
1240  if (!resultRelInfo->ri_ChildToRootMapValid)
1241  {
1242  ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1243 
1244  if (rootRelInfo)
1245  resultRelInfo->ri_ChildToRootMap =
1247  RelationGetDescr(rootRelInfo->ri_RelationDesc));
1248  else /* this isn't a child result rel */
1249  resultRelInfo->ri_ChildToRootMap = NULL;
1250 
1251  resultRelInfo->ri_ChildToRootMapValid = true;
1252  }
1253 
1254  return resultRelInfo->ri_ChildToRootMap;
1255 }
TupleConversionMap * ri_ChildToRootMap
Definition: execnodes.h:554
bool ri_ChildToRootMapValid
Definition: execnodes.h:555
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 1340 of file execUtils.c.

1341 {
1342  /* Compute the info if we didn't already */
1343  if (relinfo->ri_GeneratedExprsU == NULL)
1344  ExecInitStoredGenerated(relinfo, estate, CMD_UPDATE);
1345  return relinfo->ri_extraUpdatedCols;
1346 }
void ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype)
Bitmapset * ri_extraUpdatedCols
Definition: execnodes.h:468
ExprState ** ri_GeneratedExprsU
Definition: execnodes.h:523

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

1299 {
1300  RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
1301 
1302  if (perminfo == NULL)
1303  return NULL;
1304 
1305  /* Map the columns to child's attribute numbers if needed. */
1306  if (relinfo->ri_RootResultRelInfo)
1307  {
1308  TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1309 
1310  if (map)
1311  return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
1312  }
1313 
1314  return perminfo->insertedCols;
1315 }
static RTEPermissionInfo * GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1361
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1263
Bitmapset * insertedCols
Definition: parsenodes.h:1249
AttrMap * attrMap
Definition: tupconvert.h:28
Bitmapset * execute_attr_map_cols(AttrMap *attrMap, Bitmapset *in_cols)
Definition: tupconvert.c:252

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

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

◆ ExecGetJunkAttribute()

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

Definition at line 190 of file executor.h.

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

References Assert(), and slot_getattr().

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

◆ ExecGetRangeTableRelation()

Relation ExecGetRangeTableRelation ( EState estate,
Index  rti 
)

Definition at line 793 of file execUtils.c.

794 {
795  Relation rel;
796 
797  Assert(rti > 0 && rti <= estate->es_range_table_size);
798 
799  rel = estate->es_relations[rti - 1];
800  if (rel == NULL)
801  {
802  /* First time through, so open the relation */
803  RangeTblEntry *rte = exec_rt_fetch(rti, estate);
804 
805  Assert(rte->rtekind == RTE_RELATION);
806 
807  if (!IsParallelWorker())
808  {
809  /*
810  * In a normal query, we should already have the appropriate lock,
811  * but verify that through an Assert. Since there's already an
812  * Assert inside table_open that insists on holding some lock, it
813  * seems sufficient to check this only when rellockmode is higher
814  * than the minimum.
815  */
816  rel = table_open(rte->relid, NoLock);
818  CheckRelationLockedByMe(rel, rte->rellockmode, false));
819  }
820  else
821  {
822  /*
823  * If we are a parallel worker, we need to obtain our own local
824  * lock on the relation. This ensures sane behavior in case the
825  * parent process exits before we do.
826  */
827  rel = table_open(rte->relid, rte->rellockmode);
828  }
829 
830  estate->es_relations[rti - 1] = rel;
831  }
832 
833  return rel;
834 }
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:587
#define IsParallelWorker()
Definition: parallel.h:61
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition: lmgr.c:331
#define AccessShareLock
Definition: lockdefs.h:36
@ RTE_RELATION
Definition: parsenodes.h:1014
RTEKind rtekind
Definition: parsenodes.h:1033

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

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

◆ ExecGetResultRelCheckAsUser()

Oid ExecGetResultRelCheckAsUser ( ResultRelInfo relInfo,
EState estate 
)

Definition at line 1412 of file execUtils.c.

1413 {
1414  RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relInfo, estate);
1415 
1416  /* XXX - maybe ok to return GetUserId() in this case? */
1417  if (perminfo == NULL)
1418  elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
1419  RelationGetRelid(relInfo->ri_RelationDesc));
1420 
1421  return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
1422 }

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

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

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

1214 {
1215  if (relInfo->ri_ReturningSlot == NULL)
1216  {
1217  Relation rel = relInfo->ri_RelationDesc;
1218  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1219 
1220  relInfo->ri_ReturningSlot =
1221  ExecInitExtraTupleSlot(estate,
1222  RelationGetDescr(rel),
1223  table_slot_callbacks(rel));
1224 
1225  MemoryContextSwitchTo(oldcontext);
1226  }
1227 
1228  return relInfo->ri_ReturningSlot;
1229 }
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1832
TupleTableSlot * ri_ReturningSlot
Definition: execnodes.h:492
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 1263 of file execUtils.c.

1264 {
1265  /* Mustn't get called for a non-child result relation. */
1266  Assert(resultRelInfo->ri_RootResultRelInfo);
1267 
1268  /* If we didn't already do so, compute the map for this child. */
1269  if (!resultRelInfo->ri_RootToChildMapValid)
1270  {
1271  ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1272  TupleDesc indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
1273  TupleDesc outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1274  Relation childrel = resultRelInfo->ri_RelationDesc;
1275  AttrMap *attrMap;
1276  MemoryContext oldcontext;
1277 
1278  /*
1279  * When this child table is not a partition (!relispartition), it may
1280  * have columns that are not present in the root table, which we ask
1281  * to ignore by passing true for missing_ok.
1282  */
1283  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1284  attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
1285  !childrel->rd_rel->relispartition);
1286  if (attrMap)
1287  resultRelInfo->ri_RootToChildMap =
1288  convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
1289  MemoryContextSwitchTo(oldcontext);
1290  resultRelInfo->ri_RootToChildMapValid = true;
1291  }
1292 
1293  return resultRelInfo->ri_RootToChildMap;
1294 }
TupleConversionMap * ri_RootToChildMap
Definition: execnodes.h:560
bool ri_RootToChildMapValid
Definition: execnodes.h:561
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 1191 of file execUtils.c.

1192 {
1193  if (relInfo->ri_TrigNewSlot == NULL)
1194  {
1195  Relation rel = relInfo->ri_RelationDesc;
1196  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1197 
1198  relInfo->ri_TrigNewSlot =
1199  ExecInitExtraTupleSlot(estate,
1200  RelationGetDescr(rel),
1201  table_slot_callbacks(rel));
1202 
1203  MemoryContextSwitchTo(oldcontext);
1204  }
1205 
1206  return relInfo->ri_TrigNewSlot;
1207 }
TupleTableSlot * ri_TrigNewSlot
Definition: execnodes.h:494

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 (