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_REWIND   0x0002 /* need efficient rescan */
 
#define EXEC_FLAG_BACKWARD   0x0004 /* need backward scan */
 
#define EXEC_FLAG_MARK   0x0008 /* need mark/restore */
 
#define EXEC_FLAG_SKIP_TRIGGERS   0x0010 /* skip AfterTrigger calls */
 
#define EXEC_FLAG_WITH_NO_DATA   0x0020 /* rel scannability doesn't matter */
 
#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 *, bool)
 
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 ExecCheckRTPerms (List *rangeTable, 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)
 
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
 
TupleTableSlotEvalPlanQualSlot (EPQState *epqstate, Relation relation, Index rti)
 
bool EvalPlanQualFetchRowMark (EPQState *epqstate, Index rti, TupleTableSlot *slot)
 
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
 
void EvalPlanQualBegin (EPQState *epqstate)
 
void EvalPlanQualEnd (EPQState *epqstate)
 
PlanStateExecInitNode (Plan *node, EState *estate, int eflags)
 
void ExecSetExecProcNode (PlanState *node, ExecProcNodeMtd function)
 
NodeMultiExecProcNode (PlanState *node)
 
void ExecEndNode (PlanState *node)
 
void ExecShutdownNode (PlanState *node)
 
void ExecSetTupleBound (int64 tuples_needed, PlanState *child_node)
 
static TupleTableSlotExecProcNode (PlanState *node)
 
ExprStateExecInitExpr (Expr *node, PlanState *parent)
 
ExprStateExecInitExprWithParams (Expr *node, ParamListInfo ext_params)
 
ExprStateExecInitQual (List *qual, PlanState *parent)
 
ExprStateExecInitCheck (List *qual, PlanState *parent)
 
ListExecInitExprList (List *nodes, PlanState *parent)
 
ExprStateExecBuildAggTrans (AggState *aggstate, struct AggStatePerPhaseData *phase, bool doSort, bool doHash, bool nullcheck)
 
ExprStateExecBuildGroupingEqual (TupleDesc ldesc, TupleDesc rdesc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, int numCols, const AttrNumber *keyColIdx, const Oid *eqfunctions, const Oid *collations, PlanState *parent)
 
ExprStateExecBuildParamSetEqual (TupleDesc desc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, const Oid *eqfunctions, const Oid *collations, const List *param_exprs, PlanState *parent)
 
ProjectionInfoExecBuildProjectionInfo (List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
 
ProjectionInfoExecBuildUpdateProjection (List *targetList, bool evalTargetList, List *targetColnos, TupleDesc relDesc, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent)
 
ExprStateExecPrepareExpr (Expr *node, EState *estate)
 
ExprStateExecPrepareQual (List *qual, EState *estate)
 
ExprStateExecPrepareCheck (List *qual, EState *estate)
 
ListExecPrepareExprList (List *nodes, EState *estate)
 
static Datum ExecEvalExpr (ExprState *state, ExprContext *econtext, bool *isNull)
 
static Datum ExecEvalExprSwitchContext (ExprState *state, ExprContext *econtext, bool *isNull)
 
static TupleTableSlotExecProject (ProjectionInfo *projInfo)
 
static bool ExecQual (ExprState *state, ExprContext *econtext)
 
static bool ExecQualAndReset (ExprState *state, ExprContext *econtext)
 
bool ExecCheck (ExprState *state, ExprContext *econtext)
 
SetExprStateExecInitTableFunctionResult (Expr *expr, ExprContext *econtext, PlanState *parent)
 
TuplestorestateExecMakeTableFunctionResult (SetExprState *setexpr, ExprContext *econtext, MemoryContext argContext, TupleDesc expectedDesc, bool randomAccess)
 
SetExprStateExecInitFunctionResultSet (Expr *expr, ExprContext *econtext, PlanState *parent)
 
Datum ExecMakeFunctionResultSet (SetExprState *fcache, ExprContext *econtext, MemoryContext argContext, bool *isNull, ExprDoneCond *isDone)
 
TupleTableSlotExecScan (ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
 
void ExecAssignScanProjectionInfo (ScanState *node)
 
void ExecAssignScanProjectionInfoWithVarno (ScanState *node, int varno)
 
void ExecScanReScan (ScanState *node)
 
void ExecInitResultTypeTL (PlanState *planstate)
 
void ExecInitResultSlot (PlanState *planstate, const TupleTableSlotOps *tts_ops)
 
void ExecInitResultTupleSlotTL (PlanState *planstate, const TupleTableSlotOps *tts_ops)
 
void ExecInitScanTupleSlot (EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
 
TupleTableSlotExecInitExtraTupleSlot (EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
 
TupleTableSlotExecInitNullTupleSlot (EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
 
TupleDesc ExecTypeFromTL (List *targetList)
 
TupleDesc ExecCleanTypeFromTL (List *targetList)
 
TupleDesc ExecTypeFromExprList (List *exprList)
 
void ExecTypeSetColNames (TupleDesc typeInfo, List *namesList)
 
void UpdateChangedParamSet (PlanState *node, Bitmapset *newchg)
 
TupOutputStatebegin_tup_output_tupdesc (DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
 
void do_tup_output (TupOutputState *tstate, Datum *values, bool *isnull)
 
void do_text_output_multiline (TupOutputState *tstate, const char *txt)
 
void end_tup_output (TupOutputState *tstate)
 
EStateCreateExecutorState (void)
 
void FreeExecutorState (EState *estate)
 
ExprContextCreateExprContext (EState *estate)
 
ExprContextCreateWorkExprContext (EState *estate)
 
ExprContextCreateStandaloneExprContext (void)
 
void FreeExprContext (ExprContext *econtext, bool isCommit)
 
void ReScanExprContext (ExprContext *econtext)
 
ExprContextMakePerTupleExprContext (EState *estate)
 
void ExecAssignExprContext (EState *estate, PlanState *planstate)
 
TupleDesc ExecGetResultType (PlanState *planstate)
 
const TupleTableSlotOpsExecGetResultSlotOps (PlanState *planstate, bool *isfixed)
 
void ExecAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc)
 
void ExecConditionalAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc, int varno)
 
void ExecFreeExprContext (PlanState *planstate)
 
void ExecAssignScanType (ScanState *scanstate, TupleDesc tupDesc)
 
void ExecCreateScanSlotFromOuterPlan (EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
 
bool ExecRelationIsTargetRelation (EState *estate, Index scanrelid)
 
Relation ExecOpenScanRelation (EState *estate, Index scanrelid, int eflags)
 
void ExecInitRangeTable (EState *estate, List *rangeTable)
 
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)
 
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 ExecCheckIndexConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, List *arbiterIndexes)
 
void check_exclusion_constraint (Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex)
 
bool RelationFindReplTupleByIndex (Relation rel, Oid idxoid, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
bool RelationFindReplTupleSeq (Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
 
void ExecSimpleRelationInsert (ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot)
 
void ExecSimpleRelationUpdate (ResultRelInfo *resultRelInfo, EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot)
 
void ExecSimpleRelationDelete (ResultRelInfo *resultRelInfo, EState *estate, EPQState *epqstate, TupleTableSlot *searchslot)
 
void CheckCmdReplicaIdentity (Relation rel, CmdType cmd)
 
void CheckSubscriptionRelkind (char relkind, const char *nspname, const char *relname)
 
TupleTableSlotExecGetUpdateNewTuple (ResultRelInfo *relinfo, TupleTableSlot *planSlot, TupleTableSlot *oldSlot)
 
ResultRelInfoExecLookupResultRelByOid (ModifyTableState *node, Oid resultoid, bool missing_ok, bool update_cache)
 

Variables

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

Macro Definition Documentation

◆ do_text_output_oneline

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

Definition at line 507 of file executor.h.

◆ EvalPlanQualSetSlot

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

Definition at line 229 of file executor.h.

◆ EXEC_FLAG_BACKWARD

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

Definition at line 58 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_ONLY

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

Definition at line 56 of file executor.h.

◆ EXEC_FLAG_MARK

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

Definition at line 59 of file executor.h.

◆ EXEC_FLAG_REWIND

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

Definition at line 57 of file executor.h.

◆ EXEC_FLAG_SKIP_TRIGGERS

#define EXEC_FLAG_SKIP_TRIGGERS   0x0010 /* skip AfterTrigger calls */

Definition at line 60 of file executor.h.

◆ EXEC_FLAG_WITH_NO_DATA

#define EXEC_FLAG_WITH_NO_DATA   0x0020 /* rel scannability doesn't matter */

Definition at line 61 of file executor.h.

◆ GetPerTupleExprContext

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

Definition at line 535 of file executor.h.

◆ GetPerTupleMemoryContext

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

Definition at line 540 of file executor.h.

◆ ResetExprContext

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

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 458 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 459 of file executor.h.

◆ ExecutorCheckPerms_hook_type

typedef bool(* ExecutorCheckPerms_hook_type) (List *, bool)

Definition at line 84 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 80 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 76 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 69 of file executor.h.

◆ ExecutorStart_hook_type

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

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

2258 {
2259  TupOutputState *tstate;
2260 
2261  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2262 
2263  tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2264  tstate->dest = dest;
2265 
2266  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2267 
2268  return tstate;
2269 }
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1238
void * palloc(Size size)
Definition: mcxt.c:1199
@ CMD_SELECT
Definition: nodes.h:265
TupleTableSlot * slot
Definition: executor.h:491
DestReceiver * dest
Definition: executor.h:492
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:122

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

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

◆ BuildTupleHashTable()

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

Definition at line 255 of file execGrouping.c.

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

References BuildTupleHashTableExt().

◆ BuildTupleHashTableExt()

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

Definition at line 154 of file execGrouping.c.

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

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

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

◆ check_exclusion_constraint()

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

Definition at line 893 of file execIndexing.c.

898 {
899  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
900  values, isnull,
901  estate, newIndex,
902  CEOUC_WAIT, false, NULL);
903 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool violationOK, ItemPointer conflictTid)
Definition: execIndexing.c:667
@ 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 568 of file execReplication.c.

569 {
570  PublicationDesc pubdesc;
571 
572  /*
573  * Skip checking the replica identity for partitioned tables, because the
574  * operations are actually performed on the leaf partitions.
575  */
576  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
577  return;
578 
579  /* We only need to do checks for UPDATE and DELETE. */
580  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
581  return;
582 
583  /*
584  * It is only safe to execute UPDATE/DELETE when all columns, referenced
585  * in the row filters from publications which the relation is in, are
586  * valid - i.e. when all referenced columns are part of REPLICA IDENTITY
587  * or the table does not publish UPDATEs or DELETEs.
588  *
589  * XXX We could optimize it by first checking whether any of the
590  * publications have a row filter for this relation. If not and relation
591  * has replica identity then we can avoid building the descriptor but as
592  * this happens only one time it doesn't seem worth the additional
593  * complexity.
594  */
595  RelationBuildPublicationDesc(rel, &pubdesc);
596  if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
597  ereport(ERROR,
598  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
599  errmsg("cannot update table \"%s\"",
601  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
602  else if (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
603  ereport(ERROR,
604  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
605  errmsg("cannot update table \"%s\"",
607  errdetail("Column list used by the publication does not cover the replica identity.")));
608  else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
609  ereport(ERROR,
610  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
611  errmsg("cannot delete from table \"%s\"",
613  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
614  else if (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
615  ereport(ERROR,
616  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
617  errmsg("cannot delete from table \"%s\"",
619  errdetail("Column list used by the publication does not cover the replica identity.")));
620 
621  /* If relation has replica identity we are always good. */
623  return;
624 
625  /* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */
626  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
627  return;
628 
629  /*
630  * This is UPDATE/DELETE and there is no replica identity.
631  *
632  * Check if the table publishes UPDATES or DELETES.
633  */
634  if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
635  ereport(ERROR,
636  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
637  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
639  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
640  else if (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
641  ereport(ERROR,
642  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
643  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
645  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
646 }
#define OidIsValid(objectId)
Definition: c.h:711
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errhint(const char *fmt,...)
Definition: elog.c:1153
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
#define RelationGetRelationName(relation)
Definition: rel.h:535
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Definition: relcache.c:5618
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4947
PublicationActions pubactions
bool cols_valid_for_delete
bool cols_valid_for_update
Form_pg_class rd_rel
Definition: rel.h:110

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 655 of file execReplication.c.

657 {
658  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
659  ereport(ERROR,
660  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
661  errmsg("cannot use relation \"%s.%s\" as logical replication target",
662  nspname, relname),
664 }
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 995 of file execMain.c.

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

91 {
92  EState *estate;
93  MemoryContext qcontext;
94  MemoryContext oldcontext;
95 
96  /*
97  * Create the per-query context for this Executor run.
98  */
100  "ExecutorState",
102 
103  /*
104  * Make the EState node within the per-query context. This way, we don't
105  * need a separate pfree() operation for it at shutdown.
106  */
107  oldcontext = MemoryContextSwitchTo(qcontext);
108 
109  estate = makeNode(EState);
110 
111  /*
112  * Initialize all fields of the Executor State structure
113  */
115  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
116  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
117  estate->es_range_table = NIL;
118  estate->es_range_table_size = 0;
119  estate->es_relations = NULL;
120  estate->es_rowmarks = NULL;
121  estate->es_plannedstmt = NULL;
122  estate->es_part_prune_infos = NIL;
123 
124  estate->es_junkFilter = NULL;
125 
126  estate->es_output_cid = (CommandId) 0;
127 
128  estate->es_result_relations = NULL;
132  estate->es_trig_target_relations = NIL;
133 
134  estate->es_param_list_info = NULL;
135  estate->es_param_exec_vals = NULL;
136 
137  estate->es_queryEnv = NULL;
138 
139  estate->es_query_cxt = qcontext;
140 
141  estate->es_tupleTable = NIL;
142 
143  estate->es_processed = 0;
144 
145  estate->es_top_eflags = 0;
146  estate->es_instrument = 0;
147  estate->es_finished = false;
148 
149  estate->es_exprcontexts = NIL;
150 
151  estate->es_subplanstates = NIL;
152 
153  estate->es_auxmodifytables = NIL;
154 
155  estate->es_per_tuple_exprcontext = NULL;
156 
157  estate->es_sourceText = NULL;
158 
159  estate->es_use_parallel_mode = false;
160 
161  estate->es_jit_flags = 0;
162  estate->es_jit = NULL;
163 
164  /*
165  * Return the executor state structure
166  */
167  MemoryContextSwitchTo(oldcontext);
168 
169  return estate;
170 }
uint32 CommandId
Definition: c.h:602
MemoryContext CurrentMemoryContext
Definition: mcxt.c:124
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define makeNode(_type_)
Definition: nodes.h:165
#define NIL
Definition: pg_list.h:66
@ ForwardScanDirection
Definition: sdir.h:26
#define InvalidSnapshot
Definition: snapshot.h:123
uint64 es_processed
Definition: execnodes.h:659
List * es_part_prune_infos
Definition: execnodes.h:621
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:618
List * es_tuple_routing_result_relations
Definition: execnodes.h:643
int es_top_eflags
Definition: execnodes.h:661
struct JitContext * es_jit
Definition: execnodes.h:701
int es_instrument
Definition: execnodes.h:662
PlannedStmt * es_plannedstmt
Definition: execnodes.h:620
QueryEnvironment * es_queryEnv
Definition: execnodes.h:652
ResultRelInfo ** es_result_relations
Definition: execnodes.h:630
ParamExecData * es_param_exec_vals
Definition: execnodes.h:650
List * es_range_table
Definition: execnodes.h:614
List * es_exprcontexts
Definition: execnodes.h:665
ParamListInfo es_param_list_info
Definition: execnodes.h:649
bool es_finished
Definition: execnodes.h:663
List * es_insert_pending_result_relations
Definition: execnodes.h:708
MemoryContext es_query_cxt
Definition: execnodes.h:655
List * es_tupleTable
Definition: execnodes.h:657
ScanDirection es_direction
Definition: execnodes.h:611
List * es_trig_target_relations
Definition: execnodes.h:646
int es_jit_flags
Definition: execnodes.h:700
List * es_opened_result_relations
Definition: execnodes.h:633
bool es_use_parallel_mode
Definition: execnodes.h:686
Relation * es_relations
Definition: execnodes.h:616
List * es_subplanstates
Definition: execnodes.h:667
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:676
CommandId es_output_cid
Definition: execnodes.h:627
Index es_range_table_size
Definition: execnodes.h:615
const char * es_sourceText
Definition: execnodes.h:622
Snapshot es_snapshot
Definition: execnodes.h:612
List * es_auxmodifytables
Definition: execnodes.h:669
JunkFilter * es_junkFilter
Definition: execnodes.h:624
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:613

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_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_part_prune_infos, EState::es_per_tuple_exprcontext, EState::es_plannedstmt, EState::es_processed, EState::es_query_cxt, EState::es_queryEnv, EState::es_range_table, EState::es_range_table_size, EState::es_relations, EState::es_result_relations, EState::es_rowmarks, EState::es_snapshot, EState::es_sourceText, EState::es_subplanstates, EState::es_top_eflags, 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(), 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 303 of file execUtils.c.

304 {
306 }
static ExprContext * CreateExprContextInternal(EState *estate, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: execUtils.c:233

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 354 of file execUtils.c.

355 {
356  ExprContext *econtext;
357 
358  /* Create the ExprContext node within the caller's memory context */
359  econtext = makeNode(ExprContext);
360 
361  /* Initialize fields of ExprContext */
362  econtext->ecxt_scantuple = NULL;
363  econtext->ecxt_innertuple = NULL;
364  econtext->ecxt_outertuple = NULL;
365 
367 
368  /*
369  * Create working memory for expression evaluation in this context.
370  */
371  econtext->ecxt_per_tuple_memory =
373  "ExprContext",
375 
376  econtext->ecxt_param_exec_vals = NULL;
377  econtext->ecxt_param_list_info = NULL;
378 
379  econtext->ecxt_aggvalues = NULL;
380  econtext->ecxt_aggnulls = NULL;
381 
382  econtext->caseValue_datum = (Datum) 0;
383  econtext->caseValue_isNull = true;
384 
385  econtext->domainValue_datum = (Datum) 0;
386  econtext->domainValue_isNull = true;
387 
388  econtext->ecxt_estate = NULL;
389 
390  econtext->ecxt_callbacks = NULL;
391 
392  return econtext;
393 }
uintptr_t Datum
Definition: postgres.h:412
Datum domainValue_datum
Definition: execnodes.h:278
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:259
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:255
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:249
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:258
Datum * ecxt_aggvalues
Definition: execnodes.h:266
bool caseValue_isNull
Definition: execnodes.h:274
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:247
Datum caseValue_datum
Definition: execnodes.h:272
bool * ecxt_aggnulls
Definition: execnodes.h:268
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:254
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:286
bool domainValue_isNull
Definition: execnodes.h:280
struct EState * ecxt_estate
Definition: execnodes.h:283
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:251

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

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

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

Referenced by ExecInitAgg().

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 2303 of file execTuples.c.

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

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

Referenced by ExplainQuery().

◆ do_tup_output()

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

Definition at line 2275 of file execTuples.c.

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

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

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

2466 {
2467  TupleTableSlot *slot;
2468  TupleTableSlot *testslot;
2469 
2470  Assert(rti > 0);
2471 
2472  /*
2473  * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2474  */
2475  EvalPlanQualBegin(epqstate);
2476 
2477  /*
2478  * Callers will often use the EvalPlanQualSlot to store the tuple to avoid
2479  * an unnecessary copy.
2480  */
2481  testslot = EvalPlanQualSlot(epqstate, relation, rti);
2482  if (testslot != inputslot)
2483  ExecCopySlot(testslot, inputslot);
2484 
2485  /*
2486  * Run the EPQ query. We assume it will return at most one tuple.
2487  */
2488  slot = EvalPlanQualNext(epqstate);
2489 
2490  /*
2491  * If we got a tuple, force the slot to materialize the tuple so that it
2492  * is not dependent on any local state in the EPQ query (in particular,
2493  * it's highly likely that the slot contains references to any pass-by-ref
2494  * datums that may be present in copyTuple). As with the next step, this
2495  * is to guard against early re-use of the EPQ query.
2496  */
2497  if (!TupIsNull(slot))
2498  ExecMaterializeSlot(slot);
2499 
2500  /*
2501  * Clear out the test tuple. This is needed in case the EPQ query is
2502  * re-used to test a tuple for a different relation. (Not clear that can
2503  * really happen, but let's be safe.)
2504  */
2505  ExecClearTuple(testslot);
2506 
2507  return slot;
2508 }
void EvalPlanQualBegin(EPQState *epqstate)
Definition: execMain.c:2727
TupleTableSlot * EvalPlanQualNext(EPQState *epqstate)
Definition: execMain.c:2711
TupleTableSlot * EvalPlanQualSlot(EPQState *epqstate, Relation relation, Index rti)
Definition: execMain.c:2574
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:483
#define TupIsNull(slot)
Definition: tuptable.h:300
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:451

References Assert(), EvalPlanQualBegin(), EvalPlanQualNext(), EvalPlanQualSlot(), ExecClearTuple(), ExecCopySlot(), ExecMaterializeSlot(), and TupIsNull.

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2727 of file execMain.c.

2728 {
2729  EState *parentestate = epqstate->parentestate;
2730  EState *recheckestate = epqstate->recheckestate;
2731 
2732  if (recheckestate == NULL)
2733  {
2734  /* First time through, so create a child EState */
2735  EvalPlanQualStart(epqstate, epqstate->plan);
2736  }
2737  else
2738  {
2739  /*
2740  * We already have a suitable child EPQ tree, so just reset it.
2741  */
2742  Index rtsize = parentestate->es_range_table_size;
2743  PlanState *rcplanstate = epqstate->recheckplanstate;
2744 
2745  MemSet(epqstate->relsubs_done, 0, rtsize * sizeof(bool));
2746 
2747  /* Recopy current values of parent parameters */
2748  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2749  {
2750  int i;
2751 
2752  /*
2753  * Force evaluation of any InitPlan outputs that could be needed
2754  * by the subplan, just in case they got reset since
2755  * EvalPlanQualStart (see comments therein).
2756  */
2757  ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2758  GetPerTupleExprContext(parentestate));
2759 
2760  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2761 
2762  while (--i >= 0)
2763  {
2764  /* copy value if any, but not execPlan link */
2765  recheckestate->es_param_exec_vals[i].value =
2766  parentestate->es_param_exec_vals[i].value;
2767  recheckestate->es_param_exec_vals[i].isnull =
2768  parentestate->es_param_exec_vals[i].isnull;
2769  }
2770  }
2771 
2772  /*
2773  * Mark child plan tree as needing rescan at all scan nodes. The
2774  * first ExecProcNode will take care of actually doing the rescan.
2775  */
2776  rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2777  epqstate->epqParam);
2778  }
2779 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:739
unsigned int Index
Definition: c.h:550
#define MemSet(start, val, len)
Definition: c.h:953
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition: execMain.c:2788
#define GetPerTupleExprContext(estate)
Definition: executor.h:535
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:150
Plan * plan
Definition: execnodes.h:1182
int epqParam
Definition: execnodes.h:1167
EState * parentestate
Definition: execnodes.h:1166
EState * recheckestate
Definition: execnodes.h:1196
PlanState * recheckplanstate
Definition: execnodes.h:1211
bool * relsubs_done
Definition: execnodes.h:1209
bool isnull
Definition: params.h:150
Datum value
Definition: params.h:149
Plan * plan
Definition: execnodes.h:1029
Bitmapset * chgParam
Definition: execnodes.h:1061
Bitmapset * extParam
Definition: plannodes.h:171
List * paramExecTypes
Definition: plannodes.h:94

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

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2939 of file execMain.c.

2940 {
2941  EState *estate = epqstate->recheckestate;
2942  Index rtsize;
2943  MemoryContext oldcontext;
2944  ListCell *l;
2945 
2946  rtsize = epqstate->parentestate->es_range_table_size;
2947 
2948  /*
2949  * We may have a tuple table, even if EPQ wasn't started, because we allow
2950  * use of EvalPlanQualSlot() without calling EvalPlanQualBegin().
2951  */
2952  if (epqstate->tuple_table != NIL)
2953  {
2954  memset(epqstate->relsubs_slot, 0,
2955  rtsize * sizeof(TupleTableSlot *));
2956  ExecResetTupleTable(epqstate->tuple_table, true);
2957  epqstate->tuple_table = NIL;
2958  }
2959 
2960  /* EPQ wasn't started, nothing further to do */
2961  if (estate == NULL)
2962  return;
2963 
2964  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
2965 
2966  ExecEndNode(epqstate->recheckplanstate);
2967 
2968  foreach(l, estate->es_subplanstates)
2969  {
2970  PlanState *subplanstate = (PlanState *) lfirst(l);
2971 
2972  ExecEndNode(subplanstate);
2973  }
2974 
2975  /* throw away the per-estate tuple table, some node may have used it */
2976  ExecResetTupleTable(estate->es_tupleTable, false);
2977 
2978  /* Close any result and trigger target relations attached to this EState */
2979  ExecCloseResultRelations(estate);
2980 
2981  MemoryContextSwitchTo(oldcontext);
2982 
2983  FreeExecutorState(estate);
2984 
2985  /* Mark EPQState idle */
2986  epqstate->origslot = NULL;
2987  epqstate->recheckestate = NULL;
2988  epqstate->recheckplanstate = NULL;
2989  epqstate->relsubs_rowmark = NULL;
2990  epqstate->relsubs_done = NULL;
2991 }
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1511
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1191
void FreeExecutorState(EState *estate)
Definition: execUtils.c:188
#define lfirst(lc)
Definition: pg_list.h:170
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1203
TupleTableSlot * origslot
Definition: execnodes.h:1191
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1175
List * tuple_table
Definition: execnodes.h:1174

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

2603 {
2604  ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1];
2605  ExecRowMark *erm = earm->rowmark;
2606  Datum datum;
2607  bool isNull;
2608 
2609  Assert(earm != NULL);
2610  Assert(epqstate->origslot != NULL);
2611 
2613  elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2614 
2615  /* if child rel, must check whether it produced this row */
2616  if (erm->rti != erm->prti)
2617  {
2618  Oid tableoid;
2619 
2620  datum = ExecGetJunkAttribute(epqstate->origslot,
2621  earm->toidAttNo,
2622  &isNull);
2623  /* non-locked rels could be on the inside of outer joins */
2624  if (isNull)
2625  return false;
2626 
2627  tableoid = DatumGetObjectId(datum);
2628 
2629  Assert(OidIsValid(erm->relid));
2630  if (tableoid != erm->relid)
2631  {
2632  /* this child is inactive right now */
2633  return false;
2634  }
2635  }
2636 
2637  if (erm->markType == ROW_MARK_REFERENCE)
2638  {
2639  Assert(erm->relation != NULL);
2640 
2641  /* fetch the tuple's ctid */
2642  datum = ExecGetJunkAttribute(epqstate->origslot,
2643  earm->ctidAttNo,
2644  &isNull);
2645  /* non-locked rels could be on the inside of outer joins */
2646  if (isNull)
2647  return false;
2648 
2649  /* fetch requests on foreign tables must be passed to their FDW */
2650  if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2651  {
2652  FdwRoutine *fdwroutine;
2653  bool updated = false;
2654 
2655  fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2656  /* this should have been checked already, but let's be safe */
2657  if (fdwroutine->RefetchForeignRow == NULL)
2658  ereport(ERROR,
2659  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2660  errmsg("cannot lock rows in foreign table \"%s\"",
2662 
2663  fdwroutine->RefetchForeignRow(epqstate->recheckestate,
2664  erm,
2665  datum,
2666  slot,
2667  &updated);
2668  if (TupIsNull(slot))
2669  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2670 
2671  /*
2672  * Ideally we'd insist on updated == false here, but that assumes
2673  * that FDWs can track that exactly, which they might not be able
2674  * to. So just ignore the flag.
2675  */
2676  return true;
2677  }
2678  else
2679  {
2680  /* ordinary table, fetch the tuple */
2682  (ItemPointer) DatumGetPointer(datum),
2683  SnapshotAny, slot))
2684  elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2685  return true;
2686  }
2687  }
2688  else
2689  {
2690  Assert(erm->markType == ROW_MARK_COPY);
2691 
2692  /* fetch the whole-row Var for the relation */
2693  datum = ExecGetJunkAttribute(epqstate->origslot,
2694  earm->wholeAttNo,
2695  &isNull);
2696  /* non-locked rels could be on the inside of outer joins */
2697  if (isNull)
2698  return false;
2699 
2700  ExecStoreHeapTupleDatum(datum, slot);
2701  return true;
2702  }
2703 }
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
Definition: execTuples.c:1606
static Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: executor.h:178
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:429
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:1333
@ ROW_MARK_COPY
Definition: plannodes.h:1330
@ ROW_MARK_REFERENCE
Definition: plannodes.h:1329
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:590
unsigned int Oid
Definition: postgres_ext.h:31
#define SnapshotAny
Definition: snapmgr.h:67
AttrNumber wholeAttNo
Definition: execnodes.h:760
ExecRowMark * rowmark
Definition: execnodes.h:757
AttrNumber toidAttNo
Definition: execnodes.h:759
AttrNumber ctidAttNo
Definition: execnodes.h:758
Index rti
Definition: execnodes.h:735
Index prti
Definition: execnodes.h:736
Relation relation
Definition: execnodes.h:733
RowMarkType markType
Definition: execnodes.h:738
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:1259

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 
)

Definition at line 2518 of file execMain.c.

2520 {
2521  Index rtsize = parentestate->es_range_table_size;
2522 
2523  /* initialize data not changing over EPQState's lifetime */
2524  epqstate->parentestate = parentestate;
2525  epqstate->epqParam = epqParam;
2526 
2527  /*
2528  * Allocate space to reference a slot for each potential rti - do so now
2529  * rather than in EvalPlanQualBegin(), as done for other dynamically
2530  * allocated resources, so EvalPlanQualSlot() can be used to hold tuples
2531  * that *may* need EPQ later, without forcing the overhead of
2532  * EvalPlanQualBegin().
2533  */
2534  epqstate->tuple_table = NIL;
2535  epqstate->relsubs_slot = (TupleTableSlot **)
2536  palloc0(rtsize * sizeof(TupleTableSlot *));
2537 
2538  /* ... and remember data that EvalPlanQualBegin will need */
2539  epqstate->plan = subplan;
2540  epqstate->arowMarks = auxrowmarks;
2541 
2542  /* ... and mark the EPQ state inactive */
2543  epqstate->origslot = NULL;
2544  epqstate->recheckestate = NULL;
2545  epqstate->recheckplanstate = NULL;
2546  epqstate->relsubs_rowmark = NULL;
2547  epqstate->relsubs_done = NULL;
2548 }
void * palloc0(Size size)
Definition: mcxt.c:1230
List * arowMarks
Definition: execnodes.h:1183

References EPQState::arowMarks, EPQState::epqParam, EState::es_range_table_size, NIL, EPQState::origslot, palloc0(), EPQState::parentestate, EPQState::plan, EPQState::recheckestate, EPQState::recheckplanstate, 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(), ExecInitLockRows(), and ExecInitModifyTable().

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 2711 of file execMain.c.

2712 {
2713  MemoryContext oldcontext;
2714  TupleTableSlot *slot;
2715 
2716  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2717  slot = ExecProcNode(epqstate->recheckplanstate);
2718  MemoryContextSwitchTo(oldcontext);
2719 
2720  return slot;
2721 }
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:254

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

2558 {
2559  /* If we have a live EPQ query, shut it down */
2560  EvalPlanQualEnd(epqstate);
2561  /* And set/change the plan pointer */
2562  epqstate->plan = subplan;
2563  /* The rowmarks depend on the plan, too */
2564  epqstate->arowMarks = auxrowmarks;
2565 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2939

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2574 of file execMain.c.

2576 {
2577  TupleTableSlot **slot;
2578 
2579  Assert(relation);
2580  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2581  slot = &epqstate->relsubs_slot[rti - 1];
2582 
2583  if (*slot == NULL)
2584  {
2585  MemoryContext oldcontext;
2586 
2587  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2588  *slot = table_slot_create(relation, &epqstate->tuple_table);
2589  MemoryContextSwitchTo(oldcontext);
2590  }
2591 
2592  return *slot;
2593 }
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()

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

Definition at line 537 of file execUtils.c.

539 {
540  planstate->ps_ProjInfo =
542  planstate->ps_ExprContext,
543  planstate->ps_ResultTupleSlot,
544  planstate,
545  inputDesc);
546 }
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:354
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1067
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1069
List * targetlist
Definition: plannodes.h:153

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

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

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 672 of file execUtils.c.

673 {
674  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
675 
676  ExecSetSlotDescriptor(slot, tupDesc);
677 }
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:1289

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

2395 {
2396  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2397  char resname[32];
2398 
2399  aerm->rowmark = erm;
2400 
2401  /* Look up the resjunk columns associated with this rowmark */
2402  if (erm->markType != ROW_MARK_COPY)
2403  {
2404  /* need ctid for all methods other than COPY */
2405  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2406  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2407  resname);
2408  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2409  elog(ERROR, "could not find junk %s column", resname);
2410  }
2411  else
2412  {
2413  /* need wholerow if COPY */
2414  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2415  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2416  resname);
2417  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2418  elog(ERROR, "could not find junk %s column", resname);
2419  }
2420 
2421  /* if child rel, need tableoid */
2422  if (erm->rti != erm->prti)
2423  {
2424  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2425  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2426  resname);
2427  if (!AttributeNumberIsValid(aerm->toidAttNo))
2428  elog(ERROR, "could not find junk %s column", resname);
2429  }
2430 
2431  return aerm;
2432 }
#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:737

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

3726 {
3728  ExprEvalStep scratch = {0};
3729  int maxatt = -1;
3730  List *adjust_jumps = NIL;
3731  ListCell *lc;
3732 
3733  /*
3734  * When no columns are actually compared, the result's always true. See
3735  * special case in ExecQual().
3736  */
3737  if (numCols == 0)
3738  return NULL;
3739 
3740  state->expr = NULL;
3741  state->flags = EEO_FLAG_IS_QUAL;
3742  state->parent = parent;
3743 
3744  scratch.resvalue = &state->resvalue;
3745  scratch.resnull = &state->resnull;
3746 
3747  /* compute max needed attribute */
3748  for (int natt = 0; natt < numCols; natt++)
3749  {
3750  int attno = keyColIdx[natt];
3751 
3752  if (attno > maxatt)
3753  maxatt = attno;
3754  }
3755  Assert(maxatt >= 0);
3756 
3757  /* push deform steps */
3758  scratch.opcode = EEOP_INNER_FETCHSOME;
3759  scratch.d.fetch.last_var = maxatt;
3760  scratch.d.fetch.fixed = false;
3761  scratch.d.fetch.known_desc = ldesc;
3762  scratch.d.fetch.kind = lops;
3763  if (ExecComputeSlotInfo(state, &scratch))
3764  ExprEvalPushStep(state, &scratch);
3765 
3766  scratch.opcode = EEOP_OUTER_FETCHSOME;
3767  scratch.d.fetch.last_var = maxatt;
3768  scratch.d.fetch.fixed = false;
3769  scratch.d.fetch.known_desc = rdesc;
3770  scratch.d.fetch.kind = rops;
3771  if (ExecComputeSlotInfo(state, &scratch))
3772  ExprEvalPushStep(state, &scratch);
3773 
3774  /*
3775  * Start comparing at the last field (least significant sort key). That's
3776  * the most likely to be different if we are dealing with sorted input.
3777  */
3778  for (int natt = numCols; --natt >= 0;)
3779  {
3780  int attno = keyColIdx[natt];
3781  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3782  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3783  Oid foid = eqfunctions[natt];
3784  Oid collid = collations[natt];
3785  FmgrInfo *finfo;
3786  FunctionCallInfo fcinfo;
3787  AclResult aclresult;
3788 
3789  /* Check permission to call function */
3790  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
3791  if (aclresult != ACLCHECK_OK)
3792  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3793 
3795 
3796  /* Set up the primary fmgr lookup information */
3797  finfo = palloc0(sizeof(FmgrInfo));
3798  fcinfo = palloc0(SizeForFunctionCallInfo(2));
3799  fmgr_info(foid, finfo);
3800  fmgr_info_set_expr(NULL, finfo);
3801  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3802  collid, NULL, NULL);
3803 
3804  /* left arg */
3805  scratch.opcode = EEOP_INNER_VAR;
3806  scratch.d.var.attnum = attno - 1;
3807  scratch.d.var.vartype = latt->atttypid;
3808  scratch.resvalue = &fcinfo->args[0].value;
3809  scratch.resnull = &fcinfo->args[0].isnull;
3810  ExprEvalPushStep(state, &scratch);
3811 
3812  /* right arg */
3813  scratch.opcode = EEOP_OUTER_VAR;
3814  scratch.d.var.attnum = attno - 1;
3815  scratch.d.var.vartype = ratt->atttypid;
3816  scratch.resvalue = &fcinfo->args[1].value;
3817  scratch.resnull = &fcinfo->args[1].isnull;
3818  ExprEvalPushStep(state, &scratch);
3819 
3820  /* evaluate distinctness */
3821  scratch.opcode = EEOP_NOT_DISTINCT;
3822  scratch.d.func.finfo = finfo;
3823  scratch.d.func.fcinfo_data = fcinfo;
3824  scratch.d.func.fn_addr = finfo->fn_addr;
3825  scratch.d.func.nargs = 2;
3826  scratch.resvalue = &state->resvalue;
3827  scratch.resnull = &state->resnull;
3828  ExprEvalPushStep(state, &scratch);
3829 
3830  /* then emit EEOP_QUAL to detect if result is false (or null) */
3831  scratch.opcode = EEOP_QUAL;
3832  scratch.d.qualexpr.jumpdone = -1;
3833  scratch.resvalue = &state->resvalue;
3834  scratch.resnull = &state->resnull;
3835  ExprEvalPushStep(state, &scratch);
3836  adjust_jumps = lappend_int(adjust_jumps,
3837  state->steps_len - 1);
3838  }
3839 
3840  /* adjust jump targets */
3841  foreach(lc, adjust_jumps)
3842  {
3843  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3844 
3845  Assert(as->opcode == EEOP_QUAL);
3846  Assert(as->d.qualexpr.jumpdone == -1);
3847  as->d.qualexpr.jumpdone = state->steps_len;
3848  }
3849 
3850  scratch.resvalue = NULL;
3851  scratch.resnull = NULL;
3852  scratch.opcode = EEOP_DONE;
3853  ExprEvalPushStep(state, &scratch);
3854 
3856 
3857  return state;
3858 }
AclResult
Definition: acl.h:183
@ ACLCHECK_OK
Definition: acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3485
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:4598
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2418
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2665
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:884
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:171
@ EEOP_INNER_VAR
Definition: execExpr.h:75
@ EEOP_DONE
Definition: execExpr.h:67
@ EEOP_QUAL
Definition: execExpr.h:133
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:70
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:71
@ EEOP_OUTER_VAR
Definition: execExpr.h:76
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:75
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
List * lappend_int(List *list, int datum)
Definition: list.c:356
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1590
Oid GetUserId(void)
Definition: miscinit.c:497
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
@ OBJECT_FUNCTION
Definition: parsenodes.h:1881
#define ACL_EXECUTE
Definition: parsenodes.h:90
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
#define lfirst_int(lc)
Definition: pg_list.h:171
struct ExprEvalStep::@50::@51 fetch
struct ExprEvalStep::@50::@52 var
intptr_t opcode
Definition: execExpr.h:271
Datum * resvalue
Definition: execExpr.h:274
struct ExprEvalStep::@50::@59 qualexpr
struct ExprEvalStep::@50::@57 func
union ExprEvalStep::@50 d
bool * resnull
Definition: execExpr.h:275
Definition: fmgr.h:57
PGFunction fn_addr
Definition: fmgr.h:58
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Definition: pg_list.h:52
Datum value
Definition: postgres.h:423
Definition: regguts.h:318
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert(), 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 3876 of file execExpr.c.

3883 {
3885  ExprEvalStep scratch = {0};
3886  int maxatt = list_length(param_exprs);
3887  List *adjust_jumps = NIL;
3888  ListCell *lc;
3889 
3890  state->expr = NULL;
3891  state->flags = EEO_FLAG_IS_QUAL;
3892  state->parent = parent;
3893 
3894  scratch.resvalue = &state->resvalue;
3895  scratch.resnull = &state->resnull;
3896 
3897  /* push deform steps */
3898  scratch.opcode = EEOP_INNER_FETCHSOME;
3899  scratch.d.fetch.last_var = maxatt;
3900  scratch.d.fetch.fixed = false;
3901  scratch.d.fetch.known_desc = desc;
3902  scratch.d.fetch.kind = lops;
3903  if (ExecComputeSlotInfo(state, &scratch))
3904  ExprEvalPushStep(state, &scratch);
3905 
3906  scratch.opcode = EEOP_OUTER_FETCHSOME;
3907  scratch.d.fetch.last_var = maxatt;
3908  scratch.d.fetch.fixed = false;
3909  scratch.d.fetch.known_desc = desc;
3910  scratch.d.fetch.kind = rops;
3911  if (ExecComputeSlotInfo(state, &scratch))
3912  ExprEvalPushStep(state, &scratch);
3913 
3914  for (int attno = 0; attno < maxatt; attno++)
3915  {
3916  Form_pg_attribute att = TupleDescAttr(desc, attno);
3917  Oid foid = eqfunctions[attno];
3918  Oid collid = collations[attno];
3919  FmgrInfo *finfo;
3920  FunctionCallInfo fcinfo;
3921  AclResult aclresult;
3922 
3923  /* Check permission to call function */
3924  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
3925  if (aclresult != ACLCHECK_OK)
3926  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3927 
3929 
3930  /* Set up the primary fmgr lookup information */
3931  finfo = palloc0(sizeof(FmgrInfo));
3932  fcinfo = palloc0(SizeForFunctionCallInfo(2));
3933  fmgr_info(foid, finfo);
3934  fmgr_info_set_expr(NULL, finfo);
3935  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3936  collid, NULL, NULL);
3937 
3938  /* left arg */
3939  scratch.opcode = EEOP_INNER_VAR;
3940  scratch.d.var.attnum = attno;
3941  scratch.d.var.vartype = att->atttypid;
3942  scratch.resvalue = &fcinfo->args[0].value;
3943  scratch.resnull = &fcinfo->args[0].isnull;
3944  ExprEvalPushStep(state, &scratch);
3945 
3946  /* right arg */
3947  scratch.opcode = EEOP_OUTER_VAR;
3948  scratch.d.var.attnum = attno;
3949  scratch.d.var.vartype = att->atttypid;
3950  scratch.resvalue = &fcinfo->args[1].value;
3951  scratch.resnull = &fcinfo->args[1].isnull;
3952  ExprEvalPushStep(state, &scratch);
3953 
3954  /* evaluate distinctness */
3955  scratch.opcode = EEOP_NOT_DISTINCT;
3956  scratch.d.func.finfo = finfo;
3957  scratch.d.func.fcinfo_data = fcinfo;
3958  scratch.d.func.fn_addr = finfo->fn_addr;
3959  scratch.d.func.nargs = 2;
3960  scratch.resvalue = &state->resvalue;
3961  scratch.resnull = &state->resnull;
3962  ExprEvalPushStep(state, &scratch);
3963 
3964  /* then emit EEOP_QUAL to detect if result is false (or null) */
3965  scratch.opcode = EEOP_QUAL;
3966  scratch.d.qualexpr.jumpdone = -1;
3967  scratch.resvalue = &state->resvalue;
3968  scratch.resnull = &state->resnull;
3969  ExprEvalPushStep(state, &scratch);
3970  adjust_jumps = lappend_int(adjust_jumps,
3971  state->steps_len - 1);
3972  }
3973 
3974  /* adjust jump targets */
3975  foreach(lc, adjust_jumps)
3976  {
3977  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3978 
3979  Assert(as->opcode == EEOP_QUAL);
3980  Assert(as->d.qualexpr.jumpdone == -1);
3981  as->d.qualexpr.jumpdone = state->steps_len;
3982  }
3983 
3984  scratch.resvalue = NULL;
3985  scratch.resnull = NULL;
3986  scratch.opcode = EEOP_DONE;
3987  ExprEvalPushStep(state, &scratch);
3988 
3990 
3991  return state;
3992 }

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert(), 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 354 of file execExpr.c.

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

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, ExecInitExprRec(), ExecInitExprSlots(), 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 514 of file execExpr.c.

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

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(), ExecPushExprSlots(), ExecReadyExpr(), TargetEntry::expr, ExprEvalPushStep(), exprType(), for_each_cell, forboth, format_type_be(), get_last_attnums_walker(), LastAttnumInfo::last_outer, LastAttnumInfo::last_scan, lfirst_int, lfirst_node, list_length(), makeNode, TupleDescData::natts, ExprEvalStep::opcode, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TargetEntry::resjunk, 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 854 of file execExpr.c.

855 {
856  Datum ret;
857  bool isnull;
858 
859  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
860  if (state == NULL)
861  return true;
862 
863  /* verify that expression was not compiled using ExecInitQual */
864  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
865 
866  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
867 
868  if (isnull)
869  return true;
870 
871  return DatumGetBool(ret);
872 }
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:333
static bool DatumGetBool(Datum X)
Definition: postgres.h:438

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

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

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

◆ ExecCheckRTPerms()

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

Definition at line 570 of file execMain.c.

571 {
572  ListCell *l;
573  bool result = true;
574 
575  foreach(l, rangeTable)
576  {
577  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
578 
579  result = ExecCheckRTEPerms(rte);
580  if (!result)
581  {
582  Assert(rte->rtekind == RTE_RELATION);
583  if (ereport_on_violation)
585  get_rel_name(rte->relid));
586  return false;
587  }
588  }
589 
591  result = (*ExecutorCheckPerms_hook) (rangeTable,
592  ereport_on_violation);
593  return result;
594 }
@ ACLCHECK_NO_PRIV
Definition: acl.h:185
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook
Definition: execMain.c:78
static bool ExecCheckRTEPerms(RangeTblEntry *rte)
Definition: execMain.c:601
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1985
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1910
ObjectType get_relkind_objtype(char relkind)
@ RTE_RELATION
Definition: parsenodes.h:1011
RTEKind rtekind
Definition: parsenodes.h:1030

References aclcheck_error(), ACLCHECK_NO_PRIV, Assert(), ExecCheckRTEPerms(), ExecutorCheckPerms_hook, get_rel_name(), get_rel_relkind(), get_relkind_objtype(), lfirst, RangeTblEntry::relid, RTE_RELATION, and RangeTblEntry::rtekind.

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1149 of file execUtils.c.

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

References len, lfirst_node, and TargetEntry::resjunk.

Referenced by check_sql_fn_retval(), and ExecTypeFromTLInternal().

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 1950 of file execTuples.c.

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

References ExecTypeFromTLInternal().

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 231 of file execIndexing.c.

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

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

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

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1571 of file execMain.c.

1572 {
1573  int i;
1574 
1575  for (i = 0; i < estate->es_range_table_size; i++)
1576  {
1577  if (estate->es_relations[i])
1578  table_close(estate->es_relations[i], NoLock);
1579  }
1580 }
#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 1511 of file execMain.c.

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

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

559 {
560  if (tlist_matches_tupdesc(planstate,
561  planstate->plan->targetlist,
562  varno,
563  inputDesc))
564  {
565  planstate->ps_ProjInfo = NULL;
566  planstate->resultopsset = planstate->scanopsset;
567  planstate->resultopsfixed = planstate->scanopsfixed;
568  planstate->resultops = planstate->scanops;
569  }
570  else
571  {
572  if (!planstate->ps_ResultTupleSlot)
573  {
574  ExecInitResultSlot(planstate, &TTSOpsVirtual);
575  planstate->resultops = &TTSOpsVirtual;
576  planstate->resultopsfixed = true;
577  planstate->resultopsset = true;
578  }
579  ExecAssignProjectionInfo(planstate, inputDesc);
580  }
581 }
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1779
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
Definition: execUtils.c:584
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:537
const TupleTableSlotOps * resultops
Definition: execnodes.h:1106
bool resultopsset
Definition: execnodes.h:1114
const TupleTableSlotOps * scanops
Definition: execnodes.h:1103
bool scanopsset
Definition: execnodes.h:1111
bool scanopsfixed
Definition: execnodes.h:1107
bool resultopsfixed
Definition: execnodes.h:1110

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

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

687 {
689  TupleDesc tupDesc;
690 
691  outerPlan = outerPlanState(scanstate);
692  tupDesc = ExecGetResultType(outerPlan);
693 
694  ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
695 }
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1811
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:492
#define outerPlanState(node)
Definition: execnodes.h:1125
#define outerPlan(node)
Definition: plannodes.h:183

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

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

◆ execCurrentOf()

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

Definition at line 44 of file execCurrent.c.

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

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

Referenced by TidListEval().

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 557 of file execProcnode.c.

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

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

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

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

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

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
char * resname
Definition: primnodes.h:1557

References InvalidAttrNumber, lfirst, TargetEntry::resjunk, TargetEntry::resname, 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 2371 of file execMain.c.

2372 {
2373  if (rti > 0 && rti <= estate->es_range_table_size &&
2374  estate->es_rowmarks != NULL)
2375  {
2376  ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2377 
2378  if (erm)
2379  return erm;
2380  }
2381  if (!missing_ok)
2382  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2383  return NULL;
2384 }

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

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecFreeExprContext()

◆ ExecGetAllUpdatedCols()

Bitmapset* ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1388 of file execUtils.c.

1389 {
1390  return bms_union(ExecGetUpdatedCols(relinfo, estate),
1391  ExecGetExtraUpdatedCols(relinfo, estate));
1392 }
Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1362

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

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

◆ ExecGetAncestorResultRels()

List* ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1366 of file execMain.c.

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

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

1363 {
1364  /* see ExecGetInsertedCols() */
1365  if (relinfo->ri_RangeTableIndex != 0)
1366  {
1367  RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
1368 
1369  return rte->extraUpdatedCols;
1370  }
1371  else if (relinfo->ri_RootResultRelInfo)
1372  {
1373  ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
1374  RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
1375  TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1376 
1377  if (map != NULL)
1378  return execute_attr_map_cols(map->attrMap, rte->extraUpdatedCols);
1379  else
1380  return rte->extraUpdatedCols;
1381  }
1382  else
1383  return NULL;
1384 }
TupleConversionMap * ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
Definition: execUtils.c:1262
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:573
Bitmapset * extraUpdatedCols
Definition: parsenodes.h:1185
AttrMap * attrMap
Definition: tupconvert.h:28
Bitmapset * execute_attr_map_cols(AttrMap *attrMap, Bitmapset *in_cols)
Definition: tupconvert.c:252

References TupleConversionMap::attrMap, exec_rt_fetch(), ExecGetRootToChildMap(), execute_attr_map_cols(), RangeTblEntry::extraUpdatedCols, ResultRelInfo::ri_RangeTableIndex, and ResultRelInfo::ri_RootResultRelInfo.

Referenced by ExecComputeStoredGenerated(), ExecGetAllUpdatedCols(), and index_unchanged_by_update().

◆ ExecGetInsertedCols()

Bitmapset* ExecGetInsertedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1297 of file execUtils.c.

1298 {
1299  /*
1300  * The columns are stored in the range table entry. If this ResultRelInfo
1301  * represents a partition routing target, and doesn't have an entry of its
1302  * own in the range table, fetch the parent's RTE and map the columns to
1303  * the order they are in the partition.
1304  */
1305  if (relinfo->ri_RangeTableIndex != 0)
1306  {
1307  RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
1308 
1309  return rte->insertedCols;
1310  }
1311  else if (relinfo->ri_RootResultRelInfo)
1312  {
1313  ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
1314  RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
1315  TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1316 
1317  if (map != NULL)
1318  return execute_attr_map_cols(map->attrMap, rte->insertedCols);
1319  else
1320  return rte->insertedCols;
1321  }
1322  else
1323  {
1324  /*
1325  * The relation isn't in the range table and it isn't a partition
1326  * routing target. This ResultRelInfo must've been created only for
1327  * firing triggers and the relation is not being inserted into. (See
1328  * ExecGetTriggerResultRel.)
1329  */
1330  return NULL;
1331  }
1332 }
Bitmapset * insertedCols
Definition: parsenodes.h:1183

References TupleConversionMap::attrMap, exec_rt_fetch(), ExecGetRootToChildMap(), execute_attr_map_cols(), RangeTblEntry::insertedCols, ResultRelInfo::ri_RangeTableIndex, and ResultRelInfo::ri_RootResultRelInfo.

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

◆ ExecGetJunkAttribute()

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

Definition at line 178 of file executor.h.

179 {
180  Assert(attno > 0);
181  return slot_getattr(slot, attno, isNull);
182 }
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 784 of file execUtils.c.

785 {
786  Relation rel;
787 
788  Assert(rti > 0 && rti <= estate->es_range_table_size);
789 
790  rel = estate->es_relations[rti - 1];
791  if (rel == NULL)
792  {
793  /* First time through, so open the relation */
794  RangeTblEntry *rte = exec_rt_fetch(rti, estate);
795 
796  Assert(rte->rtekind == RTE_RELATION);
797 
798  if (!IsParallelWorker())
799  {
800  /*
801  * In a normal query, we should already have the appropriate lock,
802  * but verify that through an Assert. Since there's already an
803  * Assert inside table_open that insists on holding some lock, it
804  * seems sufficient to check this only when rellockmode is higher
805  * than the minimum.
806  */
807  rel = table_open(rte->relid, NoLock);
809  CheckRelationLockedByMe(rel, rte->rellockmode, false));
810  }
811  else
812  {
813  /*
814  * If we are a parallel worker, we need to obtain our own local
815  * lock on the relation. This ensures sane behavior in case the
816  * parent process exits before we do.
817  */
818  rel = table_open(rte->relid, rte->rellockmode);
819  }
820 
821  estate->es_relations[rti - 1] = rel;
822  }
823 
824  return rel;
825 }
#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().

◆ ExecGetResultSlotOps()

const TupleTableSlotOps* ExecGetResultSlotOps ( PlanState planstate,
bool isfixed 
)

Definition at line 501 of file execUtils.c.

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

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

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

◆ ExecGetResultType()

◆ ExecGetReturningSlot()

TupleTableSlot* ExecGetReturningSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1212 of file execUtils.c.

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

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

◆ ExecGetTriggerNewSlot()

TupleTableSlot* ExecGetTriggerNewSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1190 of file execUtils.c.

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

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

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