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, const Datum *values, const bool *isnull)
 
void do_text_output_multiline (TupOutputState *tstate, const char *txt)
 
void end_tup_output (TupOutputState *tstate)
 
EStateCreateExecutorState (void)
 
void FreeExecutorState (EState *estate)
 
ExprContextCreateExprContext (EState *estate)
 
ExprContextCreateWorkExprContext (EState *estate)
 
ExprContextCreateStandaloneExprContext (void)
 
void FreeExprContext (ExprContext *econtext, bool isCommit)
 
void ReScanExprContext (ExprContext *econtext)
 
ExprContextMakePerTupleExprContext (EState *estate)
 
void ExecAssignExprContext (EState *estate, PlanState *planstate)
 
TupleDesc ExecGetResultType (PlanState *planstate)
 
const TupleTableSlotOpsExecGetResultSlotOps (PlanState *planstate, bool *isfixed)
 
void ExecAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc)
 
void ExecConditionalAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc, int varno)
 
void ExecAssignScanType (ScanState *scanstate, TupleDesc tupDesc)
 
void ExecCreateScanSlotFromOuterPlan (EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
 
bool ExecRelationIsTargetRelation (EState *estate, Index scanrelid)
 
Relation ExecOpenScanRelation (EState *estate, Index scanrelid, int eflags)
 
void ExecInitRangeTable (EState *estate, List *rangeTable, List *permInfos)
 
void ExecCloseRangeTableRelations (EState *estate)
 
void ExecCloseResultRelations (EState *estate)
 
static RangeTblEntryexec_rt_fetch (Index rti, EState *estate)
 
Relation ExecGetRangeTableRelation (EState *estate, Index rti)
 
void ExecInitResultRelation (EState *estate, ResultRelInfo *resultRelInfo, Index rti)
 
int executor_errposition (EState *estate, int location)
 
void RegisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
void UnregisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
 
Datum GetAttributeByName (HeapTupleHeader tuple, const char *attname, bool *isNull)
 
Datum GetAttributeByNum (HeapTupleHeader tuple, AttrNumber attrno, bool *isNull)
 
int ExecTargetListLength (List *targetlist)
 
int ExecCleanTargetListLength (List *targetlist)
 
TupleTableSlotExecGetTriggerOldSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleTableSlotExecGetTriggerNewSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleTableSlotExecGetReturningSlot (EState *estate, ResultRelInfo *relInfo)
 
TupleConversionMapExecGetChildToRootMap (ResultRelInfo *resultRelInfo)
 
TupleConversionMapExecGetRootToChildMap (ResultRelInfo *resultRelInfo, EState *estate)
 
Oid ExecGetResultRelCheckAsUser (ResultRelInfo *relInfo, EState *estate)
 
BitmapsetExecGetInsertedCols (ResultRelInfo *relinfo, EState *estate)
 
BitmapsetExecGetUpdatedCols (ResultRelInfo *relinfo, EState *estate)
 
BitmapsetExecGetExtraUpdatedCols (ResultRelInfo *relinfo, EState *estate)
 
BitmapsetExecGetAllUpdatedCols (ResultRelInfo *relinfo, EState *estate)
 
void ExecOpenIndices (ResultRelInfo *resultRelInfo, bool speculative)
 
void ExecCloseIndices (ResultRelInfo *resultRelInfo)
 
ListExecInsertIndexTuples (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
 
bool ExecCheckIndexConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, List *arbiterIndexes)
 
void check_exclusion_constraint (Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex)
 
StrategyNumber get_equal_strategy_number_for_am (Oid am)
 
bool RelationFindReplTupleByIndex (Relation rel, Oid idxoid, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
bool RelationFindReplTupleSeq (Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
void ExecSimpleRelationInsert (ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot)
 
void ExecSimpleRelationUpdate (ResultRelInfo *resultRelInfo, EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot)
 
void ExecSimpleRelationDelete (ResultRelInfo *resultRelInfo, EState *estate, EPQState *epqstate, TupleTableSlot *searchslot)
 
void CheckCmdReplicaIdentity (Relation rel, CmdType cmd)
 
void CheckSubscriptionRelkind (char relkind, const char *nspname, const char *relname)
 
TupleTableSlotExecGetUpdateNewTuple (ResultRelInfo *relinfo, TupleTableSlot *planSlot, TupleTableSlot *oldSlot)
 
ResultRelInfoExecLookupResultRelByOid (ModifyTableState *node, Oid resultoid, bool missing_ok, bool update_cache)
 

Variables

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

Macro Definition Documentation

◆ do_text_output_oneline

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

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

2257 {
2258  TupOutputState *tstate;
2259 
2260  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2261 
2262  tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2263  tstate->dest = dest;
2264 
2265  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2266 
2267  return tstate;
2268 }
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1237
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:115
size_t Size
Definition: c.h:594
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:3907
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:360
struct TupleHashTableData * TupleHashTable
Definition: execnodes.h:788
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:3587
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
AttrNumber * keyColIdx
Definition: execnodes.h:810
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:811
tuplehash_hash * hashtab
Definition: execnodes.h:808
MemoryContext tempcxt
Definition: execnodes.h:815
ExprState * tab_eq_func
Definition: execnodes.h:812
TupleTableSlot * tableslot
Definition: execnodes.h:817
ExprContext * exprcontext
Definition: execnodes.h:823
MemoryContext tablecxt
Definition: execnodes.h:814
TupleTableSlot * inputslot
Definition: execnodes.h:819
ExprState * cur_eq_func
Definition: execnodes.h:821
FmgrInfo * in_hash_funcs
Definition: execnodes.h:820
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133

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

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

◆ check_exclusion_constraint()

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

Definition at line 915 of file execIndexing.c.

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

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), and values.

Referenced by IndexCheckExclusion().

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 658 of file execReplication.c.

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

747 {
748  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
749  ereport(ERROR,
750  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
751  errmsg("cannot use relation \"%s.%s\" as logical replication target",
752  nspname, relname),
754 }
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 1024 of file execMain.c.

1025 {
1026  Relation resultRel = resultRelInfo->ri_RelationDesc;
1027  TriggerDesc *trigDesc = resultRel->trigdesc;
1028  FdwRoutine *fdwroutine;
1029 
1030  switch (resultRel->rd_rel->relkind)
1031  {
1032  case RELKIND_RELATION:
1033  case RELKIND_PARTITIONED_TABLE:
1034  CheckCmdReplicaIdentity(resultRel, operation);
1035  break;
1036  case RELKIND_SEQUENCE:
1037  ereport(ERROR,
1038  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1039  errmsg("cannot change sequence \"%s\"",
1040  RelationGetRelationName(resultRel))));
1041  break;
1042  case RELKIND_TOASTVALUE:
1043  ereport(ERROR,
1044  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1045  errmsg("cannot change TOAST relation \"%s\"",
1046  RelationGetRelationName(resultRel))));
1047  break;
1048  case RELKIND_VIEW:
1049 
1050  /*
1051  * Okay only if there's a suitable INSTEAD OF trigger. Messages
1052  * here should match rewriteHandler.c's rewriteTargetView and
1053  * RewriteQuery, except that we omit errdetail because we haven't
1054  * got the information handy (and given that we really shouldn't
1055  * get here anyway, it's not worth great exertion to get).
1056  */
1057  switch (operation)
1058  {
1059  case CMD_INSERT:
1060  if (!trigDesc || !trigDesc->trig_insert_instead_row)
1061  ereport(ERROR,
1062  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1063  errmsg("cannot insert into view \"%s\"",
1064  RelationGetRelationName(resultRel)),
1065  errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
1066  break;
1067  case CMD_UPDATE:
1068  if (!trigDesc || !trigDesc->trig_update_instead_row)
1069  ereport(ERROR,
1070  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1071  errmsg("cannot update view \"%s\"",
1072  RelationGetRelationName(resultRel)),
1073  errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
1074  break;
1075  case CMD_DELETE:
1076  if (!trigDesc || !trigDesc->trig_delete_instead_row)
1077  ereport(ERROR,
1078  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1079  errmsg("cannot delete from view \"%s\"",
1080  RelationGetRelationName(resultRel)),
1081  errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
1082  break;
1083  default:
1084  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1085  break;
1086  }
1087  break;
1088  case RELKIND_MATVIEW:
1090  ereport(ERROR,
1091  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1092  errmsg("cannot change materialized view \"%s\"",
1093  RelationGetRelationName(resultRel))));
1094  break;
1095  case RELKIND_FOREIGN_TABLE:
1096  /* Okay only if the FDW supports it */
1097  fdwroutine = resultRelInfo->ri_FdwRoutine;
1098  switch (operation)
1099  {
1100  case CMD_INSERT:
1101  if (fdwroutine->ExecForeignInsert == NULL)
1102  ereport(ERROR,
1103  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1104  errmsg("cannot insert into foreign table \"%s\"",
1105  RelationGetRelationName(resultRel))));
1106  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1107  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1108  ereport(ERROR,
1109  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1110  errmsg("foreign table \"%s\" does not allow inserts",
1111  RelationGetRelationName(resultRel))));
1112  break;
1113  case CMD_UPDATE:
1114  if (fdwroutine->ExecForeignUpdate == NULL)
1115  ereport(ERROR,
1116  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1117  errmsg("cannot update foreign table \"%s\"",
1118  RelationGetRelationName(resultRel))));
1119  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1120  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1121  ereport(ERROR,
1122  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1123  errmsg("foreign table \"%s\" does not allow updates",
1124  RelationGetRelationName(resultRel))));
1125  break;
1126  case CMD_DELETE:
1127  if (fdwroutine->ExecForeignDelete == NULL)
1128  ereport(ERROR,
1129  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1130  errmsg("cannot delete from foreign table \"%s\"",
1131  RelationGetRelationName(resultRel))));
1132  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1133  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1134  ereport(ERROR,
1135  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1136  errmsg("foreign table \"%s\" does not allow deletes",
1137  RelationGetRelationName(resultRel))));
1138  break;
1139  default:
1140  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1141  break;
1142  }
1143  break;
1144  default:
1145  ereport(ERROR,
1146  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1147  errmsg("cannot change relation \"%s\"",
1148  RelationGetRelationName(resultRel))));
1149  break;
1150  }
1151 }
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition: matview.c:917
@ 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:449
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:496
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:655
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
#define AllocSetContextCreate
Definition: memutils.h:126
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:150
#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:662
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:621
List * es_tuple_routing_result_relations
Definition: execnodes.h:646
int es_top_eflags
Definition: execnodes.h:667
struct JitContext * es_jit
Definition: execnodes.h:707
int es_instrument
Definition: execnodes.h:668
PlannedStmt * es_plannedstmt
Definition: execnodes.h:624
QueryEnvironment * es_queryEnv
Definition: execnodes.h:655
ResultRelInfo ** es_result_relations
Definition: execnodes.h:633
ParamExecData * es_param_exec_vals
Definition: execnodes.h:653
uint64 es_total_processed
Definition: execnodes.h:664
List * es_range_table
Definition: execnodes.h:617
List * es_rteperminfos
Definition: execnodes.h:623
List * es_exprcontexts
Definition: execnodes.h:671
ParamListInfo es_param_list_info
Definition: execnodes.h:652
bool es_finished
Definition: execnodes.h:669
List * es_insert_pending_result_relations
Definition: execnodes.h:714
MemoryContext es_query_cxt
Definition: execnodes.h:658
List * es_tupleTable
Definition: execnodes.h:660
ScanDirection es_direction
Definition: execnodes.h:614
List * es_trig_target_relations
Definition: execnodes.h:649
int es_jit_flags
Definition: execnodes.h:706
List * es_opened_result_relations
Definition: execnodes.h:636
bool es_use_parallel_mode
Definition: execnodes.h:692
Relation * es_relations
Definition: execnodes.h:619
List * es_subplanstates
Definition: execnodes.h:673
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:682
CommandId es_output_cid
Definition: execnodes.h:630
Index es_range_table_size
Definition: execnodes.h:618
List * es_insert_pending_modifytables
Definition: execnodes.h:715
const char * es_sourceText
Definition: execnodes.h:625
Snapshot es_snapshot
Definition: execnodes.h:615
List * es_auxmodifytables
Definition: execnodes.h:675
JunkFilter * es_junkFilter
Definition: execnodes.h:627
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:616

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:279
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:260
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:256
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:250
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:259
Datum * ecxt_aggvalues
Definition: execnodes.h:267
bool caseValue_isNull
Definition: execnodes.h:275
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:248
Datum caseValue_datum
Definition: execnodes.h:273
bool * ecxt_aggnulls
Definition: execnodes.h:269
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:255
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:287
bool domainValue_isNull
Definition: execnodes.h:281
struct EState * ecxt_estate
Definition: execnodes.h:284
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:252

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:127
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:147
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:148

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

2303 {
2304  Datum values[1];
2305  bool isnull[1] = {false};
2306 
2307  while (*txt)
2308  {
2309  const char *eol;
2310  int len;
2311 
2312  eol = strchr(txt, '\n');
2313  if (eol)
2314  {
2315  len = eol - txt;
2316  eol++;
2317  }
2318  else
2319  {
2320  len = strlen(txt);
2321  eol = txt + len;
2322  }
2323 
2325  do_tup_output(tstate, values, isnull);
2327  txt = eol;
2328  }
2329 }
void do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
Definition: execTuples.c:2274
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:196

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

Referenced by ExplainQuery().

◆ do_tup_output()

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

Definition at line 2274 of file execTuples.c.

2275 {
2276  TupleTableSlot *slot = tstate->slot;
2277  int natts = slot->tts_tupleDescriptor->natts;
2278 
2279  /* make sure the slot is clear */
2280  ExecClearTuple(slot);
2281 
2282  /* insert data */
2283  memcpy(slot->tts_values, values, natts * sizeof(Datum));
2284  memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2285 
2286  /* mark slot as containing a virtual tuple */
2287  ExecStoreVirtualTuple(slot);
2288 
2289  /* send the tuple to the receiver */
2290  (void) tstate->dest->receiveSlot(slot, tstate->dest);
2291 
2292  /* clean up */
2293  ExecClearTuple(slot);
2294 }
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1551
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:123
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h: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 2332 of file execTuples.c.

2333 {
2334  tstate->dest->rShutdown(tstate->dest);
2335  /* note that destroying the dest is not ours to do */
2337  pfree(tstate);
2338 }
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1253
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 2494 of file execMain.c.

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

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

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

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 3006 of file execMain.c.

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

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

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

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

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

2760 {
2761  MemoryContext oldcontext;
2762  TupleTableSlot *slot;
2763 
2764  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2765  slot = ExecProcNode(epqstate->recheckplanstate);
2766  MemoryContextSwitchTo(oldcontext);
2767 
2768  return slot;
2769 }
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 2605 of file execMain.c.

2606 {
2607  /* If we have a live EPQ query, shut it down */
2608  EvalPlanQualEnd(epqstate);
2609  /* And set/change the plan pointer */
2610  epqstate->plan = subplan;
2611  /* The rowmarks depend on the plan, too */
2612  epqstate->arowMarks = auxrowmarks;
2613 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3006

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2622 of file execMain.c.

2624 {
2625  TupleTableSlot **slot;
2626 
2627  Assert(relation);
2628  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2629  slot = &epqstate->relsubs_slot[rti - 1];
2630 
2631  if (*slot == NULL)
2632  {
2633  MemoryContext oldcontext;
2634 
2635  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2636  *slot = table_slot_create(relation, &epqstate->tuple_table);
2637  MemoryContextSwitchTo(oldcontext);
2638  }
2639 
2640  return *slot;
2641 }
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:358
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1074
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1076
List * targetlist
Definition: plannodes.h:152

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

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

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 652 of file execUtils.c.

653 {
654  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
655 
656  ExecSetSlotDescriptor(slot, tupDesc);
657 }
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:1288

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

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

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

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

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

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

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

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

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

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

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)

Definition at line 843 of file execExpr.c.

844 {
845  Datum ret;
846  bool isnull;
847 
848  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
849  if (state == NULL)
850  return true;
851 
852  /* verify that expression was not compiled using ExecInitQual */
853  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
854 
855  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
856 
857  if (isnull)
858  return true;
859 
860  return DatumGetBool(ret);
861 }
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 527 of file execIndexing.c.

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

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 
599  /*
600  * Only relation RTEs and subquery RTEs that were once relation
601  * RTEs (views) have their perminfoindex set.
602  */
603  Assert(rte->rtekind == RTE_RELATION ||
604  (rte->rtekind == RTE_SUBQUERY &&
605  rte->relkind == RELKIND_VIEW));
606 
607  (void) getRTEPermissionInfo(rteperminfos, rte);
608  /* Many-to-one mapping not allowed */
609  Assert(!bms_is_member(rte->perminfoindex, indexset));
610  indexset = bms_add_member(indexset, rte->perminfoindex);
611  }
612  }
613 
614  /* All rteperminfos are referenced */
615  Assert(bms_num_members(indexset) == list_length(rteperminfos));
616 #endif
617 
618  foreach(l, rteperminfos)
619  {
621 
622  Assert(OidIsValid(perminfo->relid));
623  result = ExecCheckOneRelPerms(perminfo);
624  if (!result)
625  {
626  if (ereport_on_violation)
629  get_rel_name(perminfo->relid));
630  return false;
631  }
632  }
633 
635  result = (*ExecutorCheckPerms_hook) (rangeTable, rteperminfos,
636  ereport_on_violation);
637  return result;
638 }
@ ACLCHECK_NO_PRIV
Definition: acl.h:183
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:685
static bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
Definition: execMain.c:645
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:79
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2007
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1932
ObjectType get_relkind_objtype(char relkind)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_SUBQUERY
Definition: parsenodes.h:1007
@ RTE_RELATION
Definition: parsenodes.h:1006
Index perminfoindex
Definition: parsenodes.h:1068
RTEKind rtekind
Definition: parsenodes.h:1025

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, RTEPermissionInfo::relid, RangeTblEntry::relkind, RTE_RELATION, RTE_SUBQUERY, and RangeTblEntry::rtekind.

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1124 of file execUtils.c.

1125 {
1126  int len = 0;
1127  ListCell *tl;
1128 
1129  foreach(tl, targetlist)
1130  {
1131  TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1132 
1133  if (!curTle->resjunk)
1134  len++;
1135  }
1136  return len;
1137 }

References len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 1949 of file execTuples.c.

1950 {
1951  return ExecTypeFromTLInternal(targetList, true);
1952 }
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
Definition: execTuples.c:1955

References ExecTypeFromTLInternal().

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 231 of file execIndexing.c.

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

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

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

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1601 of file execMain.c.

1602 {
1603  int i;
1604 
1605  for (i = 0; i < estate->es_range_table_size; i++)
1606  {
1607  if (estate->es_relations[i])
1608  table_close(estate->es_relations[i], NoLock);
1609  }
1610 }
#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 1541 of file execMain.c.

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

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:1778
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:1113
bool resultopsset
Definition: execnodes.h:1121
const TupleTableSlotOps * scanops
Definition: execnodes.h:1110
bool scanopsset
Definition: execnodes.h:1118
bool scanopsfixed
Definition: execnodes.h:1114
bool resultopsfixed
Definition: execnodes.h:1117

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

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

667 {
669  TupleDesc tupDesc;
670 
671  outerPlan = outerPlanState(scanstate);
672  tupDesc = ExecGetResultType(outerPlan);
673 
674  ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
675 }
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1810
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:498
#define outerPlanState(node)
Definition: execnodes.h:1132
#define outerPlan(node)
Definition: plannodes.h:182

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

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

◆ execCurrentOf()

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

Definition at line 44 of file execCurrent.c.

48 {
49  char *cursor_name;
50  char *table_name;
51  Portal portal;
52  QueryDesc *queryDesc;
53 
54  /* Get the cursor name --- may have to look up a parameter reference */
55  if (cexpr->cursor_name)
56  cursor_name = cexpr->cursor_name;
57  else
58  cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param);
59 
60  /* Fetch table name for possible use in error messages */
61  table_name = get_rel_name(table_oid);
62  if (table_name == NULL)
63  elog(ERROR, "cache lookup failed for relation %u", table_oid);
64 
65  /* Find the cursor's portal */
66  portal = GetPortalByName(cursor_name);
67  if (!PortalIsValid(portal))
68  ereport(ERROR,
69  (errcode(ERRCODE_UNDEFINED_CURSOR),
70  errmsg("cursor \"%s\" does not exist", cursor_name)));
71 
72  /*
73  * We have to watch out for non-SELECT queries as well as held cursors,
74  * both of which may have null queryDesc.
75  */
76  if (portal->strategy != PORTAL_ONE_SELECT)
77  ereport(ERROR,
78  (errcode(ERRCODE_INVALID_CURSOR_STATE),
79  errmsg("cursor \"%s\" is not a SELECT query",
80  cursor_name)));
81  queryDesc = portal->queryDesc;
82  if (queryDesc == NULL || queryDesc->estate == NULL)
83  ereport(ERROR,
84  (errcode(ERRCODE_INVALID_CURSOR_STATE),
85  errmsg("cursor \"%s\" is held from a previous transaction",
86  cursor_name)));
87 
88  /*
89  * We have two different strategies depending on whether the cursor uses
90  * FOR UPDATE/SHARE or not. The reason for supporting both is that the
91  * FOR UPDATE code is able to identify a target table in many cases where
92  * the other code can't, while the non-FOR-UPDATE case allows use of WHERE
93  * CURRENT OF with an insensitive cursor.
94  */
95  if (queryDesc->estate->es_rowmarks)
96  {
97  ExecRowMark *erm;
98  Index i;
99 
100  /*
101  * Here, the query must have exactly one FOR UPDATE/SHARE reference to
102  * the target table, and we dig the ctid info out of that.
103  */
104  erm = NULL;
105  for (i = 0; i < queryDesc->estate->es_range_table_size; i++)
106  {
107  ExecRowMark *thiserm = queryDesc->estate->es_rowmarks[i];
108 
109  if (thiserm == NULL ||
111  continue; /* ignore non-FOR UPDATE/SHARE items */
112 
113  if (thiserm->relid == table_oid)
114  {
115  if (erm)
116  ereport(ERROR,
117  (errcode(ERRCODE_INVALID_CURSOR_STATE),
118  errmsg("cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\"",
119  cursor_name, table_name)));
120  erm = thiserm;
121  }
122  }
123 
124  if (erm == NULL)
125  ereport(ERROR,
126  (errcode(ERRCODE_INVALID_CURSOR_STATE),
127  errmsg("cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\"",
128  cursor_name, table_name)));
129 
130  /*
131  * The cursor must have a current result row: per the SQL spec, it's
132  * an error if not.
133  */
134  if (portal->atStart || portal->atEnd)
135  ereport(ERROR,
136  (errcode(ERRCODE_INVALID_CURSOR_STATE),
137  errmsg("cursor \"%s\" is not positioned on a row",
138  cursor_name)));
139 
140  /* Return the currently scanned TID, if there is one */
141  if (ItemPointerIsValid(&(erm->curCtid)))
142  {
143  *current_tid = erm->curCtid;
144  return true;
145  }
146 
147  /*
148  * This table didn't produce the cursor's current row; some other
149  * inheritance child of the same parent must have. Signal caller to
150  * do nothing on this table.
151  */
152  return false;
153  }
154  else
155  {
156  /*
157  * Without FOR UPDATE, we dig through the cursor's plan to find the
158  * scan node. Fail if it's not there or buried underneath
159  * aggregation.
160  */
161  ScanState *scanstate;
162  bool pending_rescan = false;
163 
164  scanstate = search_plan_tree(queryDesc->planstate, table_oid,
165  &pending_rescan);
166  if (!scanstate)
167  ereport(ERROR,
168  (errcode(ERRCODE_INVALID_CURSOR_STATE),
169  errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
170  cursor_name, table_name)));
171 
172  /*
173  * The cursor must have a current result row: per the SQL spec, it's
174  * an error if not. We test this at the top level, rather than at the
175  * scan node level, because in inheritance cases any one table scan
176  * could easily not be on a row. We want to return false, not raise
177  * error, if the passed-in table OID is for one of the inactive scans.
178  */
179  if (portal->atStart || portal->atEnd)
180  ereport(ERROR,
181  (errcode(ERRCODE_INVALID_CURSOR_STATE),
182  errmsg("cursor \"%s\" is not positioned on a row",
183  cursor_name)));
184 
185  /*
186  * Now OK to return false if we found an inactive scan. It is
187  * inactive either if it's not positioned on a row, or there's a
188  * rescan pending for it.
189  */
190  if (TupIsNull(scanstate->ss_ScanTupleSlot) || pending_rescan)
191  return false;
192 
193  /*
194  * Extract TID of the scan's current row. The mechanism for this is
195  * in principle scan-type-dependent, but for most scan types, we can
196  * just dig the TID out of the physical scan tuple.
197  */
198  if (IsA(scanstate, IndexOnlyScanState))
199  {
200  /*
201  * For IndexOnlyScan, the tuple stored in ss_ScanTupleSlot may be
202  * a virtual tuple that does not have the ctid column, so we have
203  * to get the TID from xs_ctup.t_self.
204  */
205  IndexScanDesc scan = ((IndexOnlyScanState *) scanstate)->ioss_ScanDesc;
206 
207  *current_tid = scan->xs_heaptid;
208  }
209  else
210  {
211  /*
212  * Default case: try to fetch TID from the scan node's current
213  * tuple. As an extra cross-check, verify tableoid in the current
214  * tuple. If the scan hasn't provided a physical tuple, we have
215  * to fail.
216  */
217  Datum ldatum;
218  bool lisnull;
219  ItemPointer tuple_tid;
220 
221 #ifdef USE_ASSERT_CHECKING
222  ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
224  &lisnull);
225  if (lisnull)
226  ereport(ERROR,
227  (errcode(ERRCODE_INVALID_CURSOR_STATE),
228  errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
229  cursor_name, table_name)));
230  Assert(DatumGetObjectId(ldatum) == table_oid);
231 #endif
232 
233  ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
235  &lisnull);
236  if (lisnull)
237  ereport(ERROR,
238  (errcode(ERRCODE_INVALID_CURSOR_STATE),
239  errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
240  cursor_name, table_name)));
241  tuple_tid = (ItemPointer) DatumGetPointer(ldatum);
242 
243  *current_tid = *tuple_tid;
244  }
245 
246  Assert(ItemPointerIsValid(current_tid));
247 
248  return true;
249  }
250 }
static ScanState * search_plan_tree(PlanState *node, Oid table_oid, bool *pending_rescan)
Definition: execCurrent.c:314
static char * fetch_cursor_param_value(ExprContext *econtext, int paramId)
Definition: execCurrent.c:258
ItemPointerData * ItemPointer
Definition: itemptr.h:49
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition: itemptr.h:83
@ PORTAL_ONE_SELECT
Definition: portal.h:91
#define PortalIsValid(p)
Definition: portal.h:212
Portal GetPortalByName(const char *name)
Definition: portalmem.c:131
char * cursor_name
Definition: primnodes.h:1830
ItemPointerData curCtid
Definition: execnodes.h:749
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_CteScanState:
671  ExecEndCteScan((CteScanState *) node);
672  break;
673 
674  case T_ForeignScanState:
676  break;
677 
678  case T_CustomScanState:
680  break;
681 
682  /*
683  * join nodes
684  */
685  case T_NestLoopState:
686  ExecEndNestLoop((NestLoopState *) node);
687  break;
688 
689  case T_MergeJoinState:
691  break;
692 
693  case T_HashJoinState:
694  ExecEndHashJoin((HashJoinState *) node);
695  break;
696 
697  /*
698  * materialization nodes
699  */
700  case T_MaterialState:
701  ExecEndMaterial((MaterialState *) node);
702  break;
703 
704  case T_SortState:
705  ExecEndSort((SortState *) node);
706  break;
707 
708  case T_IncrementalSortState:
710  break;
711 
712  case T_MemoizeState:
713  ExecEndMemoize((MemoizeState *) node);
714  break;
715 
716  case T_GroupState:
717  ExecEndGroup((GroupState *) node);
718  break;
719 
720  case T_AggState:
721  ExecEndAgg((AggState *) node);
722  break;
723 
724  case T_WindowAggState:
726  break;
727 
728  case T_UniqueState:
729  ExecEndUnique((UniqueState *) node);
730  break;
731 
732  case T_HashState:
733  ExecEndHash((HashState *) node);
734  break;
735 
736  case T_SetOpState:
737  ExecEndSetOp((SetOpState *) node);
738  break;
739 
740  case T_LockRowsState:
741  ExecEndLockRows((LockRowsState *) node);
742  break;
743 
744  case T_LimitState:
745  ExecEndLimit((LimitState *) node);
746  break;
747 
748  /* No clean up actions for these nodes. */
749  case T_ValuesScanState:
750  case T_NamedTuplestoreScanState:
751  case T_WorkTableScanState:
752  break;
753 
754  default:
755  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
756  break;
757  }
758 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:194
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:1060
void ExecEndMergeAppend(MergeAppendState *node)
void ExecEndMergeJoin(MergeJoinState *node)
void ExecEndModifyTable(ModifyTableState *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 ExecEndWindowAgg(WindowAggState *node)
#define nodeTag(nodeptr)
Definition: nodes.h:133
void check_stack_depth(void)
Definition: postgres.c:3520

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

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

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

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:388
TupleTableSlot * jf_resultSlot
Definition: execnodes.h:390
AttrNumber * jf_cleanMap
Definition: execnodes.h:389
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:387

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

2402 {
2403  if (rti > 0 && rti <= estate->es_range_table_size &&
2404  estate->es_rowmarks != NULL)
2405  {
2406  ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2407 
2408  if (erm)
2409  return erm;
2410  }
2411  if (!missing_ok)
2412  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2413  return NULL;
2414 }

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecGetAllUpdatedCols()

Bitmapset* ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1329 of file execUtils.c.

1330 {
1331  Bitmapset *ret;
1332  MemoryContext oldcxt;
1333 
1335 
1336  ret = bms_union(ExecGetUpdatedCols(relinfo, estate),
1337  ExecGetExtraUpdatedCols(relinfo, estate));
1338 
1339  MemoryContextSwitchTo(oldcxt);
1340 
1341  return ret;
1342 }
Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1314
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:554

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

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

◆ ExecGetAncestorResultRels()

List* ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1396 of file execMain.c.

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

1212 {
1213  /* If we didn't already do so, compute the map for this child. */
1214  if (!resultRelInfo->ri_ChildToRootMapValid)
1215  {
1216  ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1217 
1218  if (rootRelInfo)
1219  resultRelInfo->ri_ChildToRootMap =
1221  RelationGetDescr(rootRelInfo->ri_RelationDesc));
1222  else /* this isn't a child result rel */
1223  resultRelInfo->ri_ChildToRootMap = NULL;
1224 
1225  resultRelInfo->ri_ChildToRootMapValid = true;
1226  }
1227 
1228  return resultRelInfo->ri_ChildToRootMap;
1229 }
TupleConversionMap * ri_ChildToRootMap
Definition: execnodes.h:553
bool ri_ChildToRootMapValid
Definition: execnodes.h:554
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 1314 of file execUtils.c.

1315 {
1316  /* Compute the info if we didn't already */
1317  if (relinfo->ri_GeneratedExprsU == NULL)
1318  ExecInitStoredGenerated(relinfo, estate, CMD_UPDATE);
1319  return relinfo->ri_extraUpdatedCols;
1320 }
void ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype)
Bitmapset * ri_extraUpdatedCols
Definition: execnodes.h:467
ExprState ** ri_GeneratedExprsU
Definition: execnodes.h:522

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

1273 {
1274  RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
1275 
1276  if (perminfo == NULL)
1277  return NULL;
1278 
1279  /* Map the columns to child's attribute numbers if needed. */
1280  if (relinfo->ri_RootResultRelInfo)
1281  {
1282  TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1283 
1284  if (map)
1285  return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
1286  }
1287 
1288  return perminfo->insertedCols;
1289 }
static RTEPermissionInfo * GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1349
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1237
Bitmapset * insertedCols
Definition: parsenodes.h:1241
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 767 of file execUtils.c.

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

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

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

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:121
#define TTS_FIXED(slot)
Definition: tuptable.h:108

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

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

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot* ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1187 of file execUtils.c.

1188 {
1189  if (relInfo->ri_ReturningSlot == NULL)
1190  {
1191  Relation rel = relInfo->ri_RelationDesc;
1192  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1193 
1194  relInfo->ri_ReturningSlot =
1195  ExecInitExtraTupleSlot(estate,
1196  RelationGetDescr(rel),
1197  table_slot_callbacks(rel));
1198 
1199  MemoryContextSwitchTo(oldcontext);
1200  }
1201 
1202  return relInfo->ri_ReturningSlot;
1203 }
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1830
TupleTableSlot * ri_ReturningSlot
Definition: execnodes.h:491
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 1237 of file execUtils.c.

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

1166 {
1167  if (relInfo->ri_TrigNewSlot == NULL)
1168  {
1169  Relation rel = relInfo->ri_RelationDesc;
1170  MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1171 
1172  relInfo->ri_TrigNewSlot =
1173  ExecInitExtraTupleSlot(estate,
1174  RelationGetDescr(rel),
1175  table_slot_callbacks(rel));
1176 
1177  MemoryContextSwitchTo(oldcontext);
1178  }
1179 
1180  return relInfo->ri_TrigNewSlot;
1181 }
TupleTableSlot * ri_TrigNewSlot
Definition: execnodes.h:493

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

Referenced by AfterTriggerExecute(), and AfterTriggerSaveEvent().

◆ ExecGetTriggerOldSlot()

TupleTableSlot* ExecGetTriggerOldSlot ( EState estate,
ResultRelInfo relInfo 
)

◆ ExecGetTriggerResultRel()

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

Definition at line 1320 of file execMain.c.

1322 {
1323  ResultRelInfo *rInfo;