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 *testslot)
 
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)
 
bool 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)
 
ExprStateExecInitExprWithCaseValue (Expr *node, PlanState *parent, Datum *caseval, bool *casenull)
 
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 *context)
 
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)
 
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)
#define DatumGetPointer(X)
Definition: postgres.h:593
#define PointerGetDatum(X)
Definition: postgres.h:600
text * cstring_to_text(const char *s)
Definition: varlena.c:188

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

◆ GetPerTupleMemoryContext

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

Definition at line 542 of file executor.h.

◆ ResetExprContext

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

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 460 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 461 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:1068
@ CMD_SELECT
Definition: nodes.h:721
TupleTableSlot * slot
Definition: executor.h:493
DestReceiver * dest
Definition: executor.h:494
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(), 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:112
size_t Size
Definition: c.h:540
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:3956
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:352
struct TupleHashTableData * TupleHashTable
Definition: execnodes.h:752
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:3401
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
AttrNumber * keyColIdx
Definition: execnodes.h:774
FmgrInfo * tab_hash_funcs
Definition: execnodes.h:775
tuplehash_hash * hashtab
Definition: execnodes.h:772
MemoryContext tempcxt
Definition: execnodes.h:779
ExprState * tab_eq_func
Definition: execnodes.h:776
TupleTableSlot * tableslot
Definition: execnodes.h:781
ExprContext * exprcontext
Definition: execnodes.h:787
MemoryContext tablecxt
Definition: execnodes.h:778
TupleTableSlot * inputslot
Definition: execnodes.h:783
ExprState * cur_eq_func
Definition: execnodes.h:785
FmgrInfo * in_hash_funcs
Definition: execnodes.h:784
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 887 of file execIndexing.c.

892 {
893  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
894  values, isnull,
895  estate, newIndex,
896  CEOUC_WAIT, false, NULL);
897 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
@ CEOUC_WAIT
Definition: execIndexing.c:122
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 errorOK, ItemPointer conflictTid)
Definition: execIndexing.c:667
Definition: type.h:90

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  /* We only need to do checks for UPDATE and DELETE. */
573  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
574  return;
575 
576  /*
577  * It is only safe to execute UPDATE/DELETE when all columns, referenced
578  * in the row filters from publications which the relation is in, are
579  * valid - i.e. when all referenced columns are part of REPLICA IDENTITY
580  * or the table does not publish UPDATEs or DELETEs.
581  *
582  * XXX We could optimize it by first checking whether any of the
583  * publications have a row filter for this relation. If not and relation
584  * has replica identity then we can avoid building the descriptor but as
585  * this happens only one time it doesn't seem worth the additional
586  * complexity.
587  */
588  RelationBuildPublicationDesc(rel, &pubdesc);
589  if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
590  ereport(ERROR,
591  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
592  errmsg("cannot update table \"%s\"",
594  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
595  else if (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
596  ereport(ERROR,
597  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
598  errmsg("cannot update table \"%s\"",
600  errdetail("Column list used by the publication does not cover the replica identity.")));
601  else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
602  ereport(ERROR,
603  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
604  errmsg("cannot delete from table \"%s\"",
606  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
607  else if (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
608  ereport(ERROR,
609  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
610  errmsg("cannot delete from table \"%s\"",
612  errdetail("Column list used by the publication does not cover the replica identity.")));
613 
614  /* If relation has replica identity we are always good. */
616  return;
617 
618  /* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */
619  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
620  return;
621 
622  /*
623  * This is UPDATE/DELETE and there is no replica identity.
624  *
625  * Check if the table publishes UPDATES or DELETES.
626  */
627  if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
628  ereport(ERROR,
629  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
630  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
632  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
633  else if (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
634  ereport(ERROR,
635  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
636  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
638  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
639 }
#define OidIsValid(objectId)
Definition: c.h:710
int errdetail(const char *fmt,...)
Definition: elog.c:1037
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
@ CMD_DELETE
Definition: nodes.h:724
@ CMD_UPDATE
Definition: nodes.h:722
#define RelationGetRelationName(relation)
Definition: rel.h:523
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Definition: relcache.c:5561
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4884
PublicationActions pubactions
bool cols_valid_for_delete
bool cols_valid_for_update
Form_pg_class rd_rel
Definition: rel.h:109

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

650 {
651  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
652  ereport(ERROR,
653  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
654  errmsg("cannot use relation \"%s.%s\" as logical replication target",
655  nspname, relname),
657 }
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(), CreateSubscription(), and logicalrep_rel_open().

◆ CheckValidResultRel()

void CheckValidResultRel ( ResultRelInfo resultRelInfo,
CmdType  operation 
)

Definition at line 994 of file execMain.c.

995 {
996  Relation resultRel = resultRelInfo->ri_RelationDesc;
997  TriggerDesc *trigDesc = resultRel->trigdesc;
998  FdwRoutine *fdwroutine;
999 
1000  switch (resultRel->rd_rel->relkind)
1001  {
1002  case RELKIND_RELATION:
1003  case RELKIND_PARTITIONED_TABLE:
1004  CheckCmdReplicaIdentity(resultRel, operation);
1005  break;
1006  case RELKIND_SEQUENCE:
1007  ereport(ERROR,
1008  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1009  errmsg("cannot change sequence \"%s\"",
1010  RelationGetRelationName(resultRel))));
1011  break;
1012  case RELKIND_TOASTVALUE:
1013  ereport(ERROR,
1014  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1015  errmsg("cannot change TOAST relation \"%s\"",
1016  RelationGetRelationName(resultRel))));
1017  break;
1018  case RELKIND_VIEW:
1019 
1020  /*
1021  * Okay only if there's a suitable INSTEAD OF trigger. Messages
1022  * here should match rewriteHandler.c's rewriteTargetView and
1023  * RewriteQuery, except that we omit errdetail because we haven't
1024  * got the information handy (and given that we really shouldn't
1025  * get here anyway, it's not worth great exertion to get).
1026  */
1027  switch (operation)
1028  {
1029  case CMD_INSERT:
1030  if (!trigDesc || !trigDesc->trig_insert_instead_row)
1031  ereport(ERROR,
1032  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1033  errmsg("cannot insert into view \"%s\"",
1034  RelationGetRelationName(resultRel)),
1035  errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
1036  break;
1037  case CMD_UPDATE:
1038  if (!trigDesc || !trigDesc->trig_update_instead_row)
1039  ereport(ERROR,
1040  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1041  errmsg("cannot update view \"%s\"",
1042  RelationGetRelationName(resultRel)),
1043  errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
1044  break;
1045  case CMD_DELETE:
1046  if (!trigDesc || !trigDesc->trig_delete_instead_row)
1047  ereport(ERROR,
1048  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1049  errmsg("cannot delete from view \"%s\"",
1050  RelationGetRelationName(resultRel)),
1051  errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
1052  break;
1053  default:
1054  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1055  break;
1056  }
1057  break;
1058  case RELKIND_MATVIEW:
1060  ereport(ERROR,
1061  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1062  errmsg("cannot change materialized view \"%s\"",
1063  RelationGetRelationName(resultRel))));
1064  break;
1065  case RELKIND_FOREIGN_TABLE:
1066  /* Okay only if the FDW supports it */
1067  fdwroutine = resultRelInfo->ri_FdwRoutine;
1068  switch (operation)
1069  {
1070  case CMD_INSERT:
1071  if (fdwroutine->ExecForeignInsert == NULL)
1072  ereport(ERROR,
1073  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1074  errmsg("cannot insert into foreign table \"%s\"",
1075  RelationGetRelationName(resultRel))));
1076  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1077  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1078  ereport(ERROR,
1079  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1080  errmsg("foreign table \"%s\" does not allow inserts",
1081  RelationGetRelationName(resultRel))));
1082  break;
1083  case CMD_UPDATE:
1084  if (fdwroutine->ExecForeignUpdate == NULL)
1085  ereport(ERROR,
1086  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1087  errmsg("cannot update foreign table \"%s\"",
1088  RelationGetRelationName(resultRel))));
1089  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1090  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1091  ereport(ERROR,
1092  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1093  errmsg("foreign table \"%s\" does not allow updates",
1094  RelationGetRelationName(resultRel))));
1095  break;
1096  case CMD_DELETE:
1097  if (fdwroutine->ExecForeignDelete == NULL)
1098  ereport(ERROR,
1099  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1100  errmsg("cannot delete from foreign table \"%s\"",
1101  RelationGetRelationName(resultRel))));
1102  if (fdwroutine->IsForeignRelUpdatable != NULL &&
1103  (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1104  ereport(ERROR,
1105  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1106  errmsg("foreign table \"%s\" does not allow deletes",
1107  RelationGetRelationName(resultRel))));
1108  break;
1109  default:
1110  elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1111  break;
1112  }
1113  break;
1114  default:
1115  ereport(ERROR,
1116  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1117  errmsg("cannot change relation \"%s\"",
1118  RelationGetRelationName(resultRel))));
1119  break;
1120  }
1121 }
#define elog(elevel,...)
Definition: elog.h:218
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
bool MatViewIncrementalMaintenanceIsEnabled(void)
Definition: matview.c:920
@ CMD_INSERT
Definition: nodes.h:723
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:115
Relation ri_RelationDesc
Definition: execnodes.h:433
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:477
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 
123  estate->es_junkFilter = NULL;
124 
125  estate->es_output_cid = (CommandId) 0;
126 
127  estate->es_result_relations = NULL;
130  estate->es_trig_target_relations = NIL;
131 
132  estate->es_param_list_info = NULL;
133  estate->es_param_exec_vals = NULL;
134 
135  estate->es_queryEnv = NULL;
136 
137  estate->es_query_cxt = qcontext;
138 
139  estate->es_tupleTable = NIL;
140 
141  estate->es_processed = 0;
142 
143  estate->es_top_eflags = 0;
144  estate->es_instrument = 0;
145  estate->es_finished = false;
146 
147  estate->es_exprcontexts = NIL;
148 
149  estate->es_subplanstates = NIL;
150 
151  estate->es_auxmodifytables = NIL;
152 
153  estate->es_per_tuple_exprcontext = NULL;
154 
155  estate->es_sourceText = NULL;
156 
157  estate->es_use_parallel_mode = false;
158 
159  estate->es_jit_flags = 0;
160  estate->es_jit = NULL;
161 
162  /*
163  * Return the executor state structure
164  */
165  MemoryContextSwitchTo(oldcontext);
166 
167  return estate;
168 }
uint32 CommandId
Definition: c.h:601
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
#define makeNode(_type_)
Definition: nodes.h:621
#define NIL
Definition: pg_list.h:65
@ ForwardScanDirection
Definition: sdir.h:26
#define InvalidSnapshot
Definition: snapshot.h:123
uint64 es_processed
Definition: execnodes.h:636
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:596
List * es_tuple_routing_result_relations
Definition: execnodes.h:620
int es_top_eflags
Definition: execnodes.h:638
struct JitContext * es_jit
Definition: execnodes.h:678
int es_instrument
Definition: execnodes.h:639
PlannedStmt * es_plannedstmt
Definition: execnodes.h:598
QueryEnvironment * es_queryEnv
Definition: execnodes.h:629
ResultRelInfo ** es_result_relations
Definition: execnodes.h:607
ParamExecData * es_param_exec_vals
Definition: execnodes.h:627
List * es_range_table
Definition: execnodes.h:592
List * es_exprcontexts
Definition: execnodes.h:642
ParamListInfo es_param_list_info
Definition: execnodes.h:626
bool es_finished
Definition: execnodes.h:640
MemoryContext es_query_cxt
Definition: execnodes.h:632
List * es_tupleTable
Definition: execnodes.h:634
ScanDirection es_direction
Definition: execnodes.h:589
List * es_trig_target_relations
Definition: execnodes.h:623
int es_jit_flags
Definition: execnodes.h:677
List * es_opened_result_relations
Definition: execnodes.h:610
bool es_use_parallel_mode
Definition: execnodes.h:663
Relation * es_relations
Definition: execnodes.h:594
List * es_subplanstates
Definition: execnodes.h:644
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:653
CommandId es_output_cid
Definition: execnodes.h:604
Index es_range_table_size
Definition: execnodes.h:593
const char * es_sourceText
Definition: execnodes.h:599
Snapshot es_snapshot
Definition: execnodes.h:590
List * es_auxmodifytables
Definition: execnodes.h:646
JunkFilter * es_junkFilter
Definition: execnodes.h:601
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:591

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, EState::es_auxmodifytables, EState::es_crosscheck_snapshot, EState::es_direction, EState::es_exprcontexts, EState::es_finished, EState::es_instrument, EState::es_jit, EState::es_jit_flags, EState::es_junkFilter, EState::es_opened_result_relations, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_per_tuple_exprcontext, EState::es_plannedstmt, EState::es_processed, EState::es_query_cxt, EState::es_queryEnv, EState::es_range_table, EState::es_range_table_size, EState::es_relations, EState::es_result_relations, EState::es_rowmarks, EState::es_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 301 of file execUtils.c.

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

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 352 of file execUtils.c.

353 {
354  ExprContext *econtext;
355 
356  /* Create the ExprContext node within the caller's memory context */
357  econtext = makeNode(ExprContext);
358 
359  /* Initialize fields of ExprContext */
360  econtext->ecxt_scantuple = NULL;
361  econtext->ecxt_innertuple = NULL;
362  econtext->ecxt_outertuple = NULL;
363 
365 
366  /*
367  * Create working memory for expression evaluation in this context.
368  */
369  econtext->ecxt_per_tuple_memory =
371  "ExprContext",
373 
374  econtext->ecxt_param_exec_vals = NULL;
375  econtext->ecxt_param_list_info = NULL;
376 
377  econtext->ecxt_aggvalues = NULL;
378  econtext->ecxt_aggnulls = NULL;
379 
380  econtext->caseValue_datum = (Datum) 0;
381  econtext->caseValue_isNull = true;
382 
383  econtext->domainValue_datum = (Datum) 0;
384  econtext->domainValue_isNull = true;
385 
386  econtext->ecxt_estate = NULL;
387 
388  econtext->ecxt_callbacks = NULL;
389 
390  return econtext;
391 }
uintptr_t Datum
Definition: postgres.h:411
Datum domainValue_datum
Definition: execnodes.h:263
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:244
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:240
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:234
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:243
Datum * ecxt_aggvalues
Definition: execnodes.h:251
bool caseValue_isNull
Definition: execnodes.h:259
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:232
Datum caseValue_datum
Definition: execnodes.h:257
bool * ecxt_aggnulls
Definition: execnodes.h:253
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:239
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:271
bool domainValue_isNull
Definition: execnodes.h:265
struct EState * ecxt_estate
Definition: execnodes.h:268
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:236

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

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

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:1175
const void size_t len
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:200

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:425

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(), 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(), ShowAllGUCConfig(), ShowGUCConfigOption(), and StartReplication().

◆ EvalPlanQual()

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

Definition at line 2457 of file execMain.c.

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

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

2721 {
2722  EState *parentestate = epqstate->parentestate;
2723  EState *recheckestate = epqstate->recheckestate;
2724 
2725  if (recheckestate == NULL)
2726  {
2727  /* First time through, so create a child EState */
2728  EvalPlanQualStart(epqstate, epqstate->plan);
2729  }
2730  else
2731  {
2732  /*
2733  * We already have a suitable child EPQ tree, so just reset it.
2734  */
2735  Index rtsize = parentestate->es_range_table_size;
2736  PlanState *rcplanstate = epqstate->recheckplanstate;
2737 
2738  MemSet(epqstate->relsubs_done, 0, rtsize * sizeof(bool));
2739 
2740  /* Recopy current values of parent parameters */
2741  if (parentestate->es_plannedstmt->paramExecTypes != NIL)
2742  {
2743  int i;
2744 
2745  /*
2746  * Force evaluation of any InitPlan outputs that could be needed
2747  * by the subplan, just in case they got reset since
2748  * EvalPlanQualStart (see comments therein).
2749  */
2750  ExecSetParamPlanMulti(rcplanstate->plan->extParam,
2751  GetPerTupleExprContext(parentestate));
2752 
2753  i = list_length(parentestate->es_plannedstmt->paramExecTypes);
2754 
2755  while (--i >= 0)
2756  {
2757  /* copy value if any, but not execPlan link */
2758  recheckestate->es_param_exec_vals[i].value =
2759  parentestate->es_param_exec_vals[i].value;
2760  recheckestate->es_param_exec_vals[i].isnull =
2761  parentestate->es_param_exec_vals[i].isnull;
2762  }
2763  }
2764 
2765  /*
2766  * Mark child plan tree as needing rescan at all scan nodes. The
2767  * first ExecProcNode will take care of actually doing the rescan.
2768  */
2769  rcplanstate->chgParam = bms_add_member(rcplanstate->chgParam,
2770  epqstate->epqParam);
2771  }
2772 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:738
unsigned int Index
Definition: c.h:549
#define MemSet(start, val, len)
Definition: c.h:1008
static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
Definition: execMain.c:2781
#define GetPerTupleExprContext(estate)
Definition: executor.h:537
int i
Definition: isn.c:73
void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext)
Definition: nodeSubplan.c:1253
static int list_length(const List *l)
Definition: pg_list.h:149
Plan * plan
Definition: execnodes.h:1151
int epqParam
Definition: execnodes.h:1136
EState * parentestate
Definition: execnodes.h:1135
EState * recheckestate
Definition: execnodes.h:1165
PlanState * recheckplanstate
Definition: execnodes.h:1180
bool * relsubs_done
Definition: execnodes.h:1178
bool isnull
Definition: params.h:150
Datum value
Definition: params.h:149
Plan * plan
Definition: execnodes.h:998
Bitmapset * chgParam
Definition: execnodes.h:1030
Bitmapset * extParam
Definition: plannodes.h:160
List * paramExecTypes
Definition: plannodes.h:85

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

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

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

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

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

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

2705 {
2706  MemoryContext oldcontext;
2707  TupleTableSlot *slot;
2708 
2709  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2710  slot = ExecProcNode(epqstate->recheckplanstate);
2711  MemoryContextSwitchTo(oldcontext);
2712 
2713  return slot;
2714 }
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 2550 of file execMain.c.

2551 {
2552  /* If we have a live EPQ query, shut it down */
2553  EvalPlanQualEnd(epqstate);
2554  /* And set/change the plan pointer */
2555  epqstate->plan = subplan;
2556  /* The rowmarks depend on the plan, too */
2557  epqstate->arowMarks = auxrowmarks;
2558 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2932

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2567 of file execMain.c.

2569 {
2570  TupleTableSlot **slot;
2571 
2572  Assert(relation);
2573  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2574  slot = &epqstate->relsubs_slot[rti - 1];
2575 
2576  if (*slot == NULL)
2577  {
2578  MemoryContext oldcontext;
2579 
2580  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2581  *slot = table_slot_create(relation, &epqstate->tuple_table);
2582  MemoryContextSwitchTo(oldcontext);
2583  }
2584 
2585  return *slot;
2586 }
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 535 of file execUtils.c.

537 {
538  planstate->ps_ProjInfo =
540  planstate->ps_ExprContext,
541  planstate->ps_ResultTupleSlot,
542  planstate,
543  inputDesc);
544 }
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:353
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1036
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1038
List * targetlist
Definition: plannodes.h:142

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

671 {
672  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
673 
674  ExecSetSlotDescriptor(slot, tupDesc);
675 }
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 2387 of file execMain.c.

2388 {
2389  ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2390  char resname[32];
2391 
2392  aerm->rowmark = erm;
2393 
2394  /* Look up the resjunk columns associated with this rowmark */
2395  if (erm->markType != ROW_MARK_COPY)
2396  {
2397  /* need ctid for all methods other than COPY */
2398  snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2399  aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2400  resname);
2401  if (!AttributeNumberIsValid(aerm->ctidAttNo))
2402  elog(ERROR, "could not find junk %s column", resname);
2403  }
2404  else
2405  {
2406  /* need wholerow if COPY */
2407  snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2408  aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2409  resname);
2410  if (!AttributeNumberIsValid(aerm->wholeAttNo))
2411  elog(ERROR, "could not find junk %s column", resname);
2412  }
2413 
2414  /* if child rel, need tableoid */
2415  if (erm->rti != erm->prti)
2416  {
2417  snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2418  aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2419  resname);
2420  if (!AttributeNumberIsValid(aerm->toidAttNo))
2421  elog(ERROR, "could not find junk %s column", resname);
2422  }
2423 
2424  return aerm;
2425 }
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:222
#define snprintf
Definition: port.h:225
Index rowmarkId
Definition: execnodes.h:708

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

3963 {
3965  ExprEvalStep scratch = {0};
3966  int maxatt = -1;
3967  List *adjust_jumps = NIL;
3968  ListCell *lc;
3969 
3970  /*
3971  * When no columns are actually compared, the result's always true. See
3972  * special case in ExecQual().
3973  */
3974  if (numCols == 0)
3975  return NULL;
3976 
3977  state->expr = NULL;
3978  state->flags = EEO_FLAG_IS_QUAL;
3979  state->parent = parent;
3980 
3981  scratch.resvalue = &state->resvalue;
3982  scratch.resnull = &state->resnull;
3983 
3984  /* compute max needed attribute */
3985  for (int natt = 0; natt < numCols; natt++)
3986  {
3987  int attno = keyColIdx[natt];
3988 
3989  if (attno > maxatt)
3990  maxatt = attno;
3991  }
3992  Assert(maxatt >= 0);
3993 
3994  /* push deform steps */
3995  scratch.opcode = EEOP_INNER_FETCHSOME;
3996  scratch.d.fetch.last_var = maxatt;
3997  scratch.d.fetch.fixed = false;
3998  scratch.d.fetch.known_desc = ldesc;
3999  scratch.d.fetch.kind = lops;
4000  if (ExecComputeSlotInfo(state, &scratch))
4001  ExprEvalPushStep(state, &scratch);
4002 
4003  scratch.opcode = EEOP_OUTER_FETCHSOME;
4004  scratch.d.fetch.last_var = maxatt;
4005  scratch.d.fetch.fixed = false;
4006  scratch.d.fetch.known_desc = rdesc;
4007  scratch.d.fetch.kind = rops;
4008  if (ExecComputeSlotInfo(state, &scratch))
4009  ExprEvalPushStep(state, &scratch);
4010 
4011  /*
4012  * Start comparing at the last field (least significant sort key). That's
4013  * the most likely to be different if we are dealing with sorted input.
4014  */
4015  for (int natt = numCols; --natt >= 0;)
4016  {
4017  int attno = keyColIdx[natt];
4018  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
4019  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
4020  Oid foid = eqfunctions[natt];
4021  Oid collid = collations[natt];
4022  FmgrInfo *finfo;
4023  FunctionCallInfo fcinfo;
4024  AclResult aclresult;
4025 
4026  /* Check permission to call function */
4027  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
4028  if (aclresult != ACLCHECK_OK)
4029  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4030 
4032 
4033  /* Set up the primary fmgr lookup information */
4034  finfo = palloc0(sizeof(FmgrInfo));
4035  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4036  fmgr_info(foid, finfo);
4037  fmgr_info_set_expr(NULL, finfo);
4038  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4039  collid, NULL, NULL);
4040 
4041  /* left arg */
4042  scratch.opcode = EEOP_INNER_VAR;
4043  scratch.d.var.attnum = attno - 1;
4044  scratch.d.var.vartype = latt->atttypid;
4045  scratch.resvalue = &fcinfo->args[0].value;
4046  scratch.resnull = &fcinfo->args[0].isnull;
4047  ExprEvalPushStep(state, &scratch);
4048 
4049  /* right arg */
4050  scratch.opcode = EEOP_OUTER_VAR;
4051  scratch.d.var.attnum = attno - 1;
4052  scratch.d.var.vartype = ratt->atttypid;
4053  scratch.resvalue = &fcinfo->args[1].value;
4054  scratch.resnull = &fcinfo->args[1].isnull;
4055  ExprEvalPushStep(state, &scratch);
4056 
4057  /* evaluate distinctness */
4058  scratch.opcode = EEOP_NOT_DISTINCT;
4059  scratch.d.func.finfo = finfo;
4060  scratch.d.func.fcinfo_data = fcinfo;
4061  scratch.d.func.fn_addr = finfo->fn_addr;
4062  scratch.d.func.nargs = 2;
4063  scratch.resvalue = &state->resvalue;
4064  scratch.resnull = &state->resnull;
4065  ExprEvalPushStep(state, &scratch);
4066 
4067  /* then emit EEOP_QUAL to detect if result is false (or null) */
4068  scratch.opcode = EEOP_QUAL;
4069  scratch.d.qualexpr.jumpdone = -1;
4070  scratch.resvalue = &state->resvalue;
4071  scratch.resnull = &state->resnull;
4072  ExprEvalPushStep(state, &scratch);
4073  adjust_jumps = lappend_int(adjust_jumps,
4074  state->steps_len - 1);
4075  }
4076 
4077  /* adjust jump targets */
4078  foreach(lc, adjust_jumps)
4079  {
4080  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4081 
4082  Assert(as->opcode == EEOP_QUAL);
4083  Assert(as->d.qualexpr.jumpdone == -1);
4084  as->d.qualexpr.jumpdone = state->steps_len;
4085  }
4086 
4087  scratch.resvalue = NULL;
4088  scratch.resnull = NULL;
4089  scratch.opcode = EEOP_DONE;
4090  ExprEvalPushStep(state, &scratch);
4091 
4093 
4094  return state;
4095 }
AclResult
Definition: acl.h:181
@ ACLCHECK_OK
Definition: acl.h:182
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3512
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:5071
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2693
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2940
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:883
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:172
@ EEOP_INNER_VAR
Definition: execExpr.h:76
@ EEOP_DONE
Definition: execExpr.h:68
@ EEOP_QUAL
Definition: execExpr.h:134
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:71
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:72
@ EEOP_OUTER_VAR
Definition: execExpr.h:77
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:60
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:354
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1589
Oid GetUserId(void)
Definition: miscinit.c:492
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:211
@ OBJECT_FUNCTION
Definition: parsenodes.h:2153
#define ACL_EXECUTE
Definition: parsenodes.h:89
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
#define lfirst_int(lc)
Definition: pg_list.h:170
struct ExprEvalStep::@52::@53 fetch
struct ExprEvalStep::@52::@59 func
struct ExprEvalStep::@52::@61 qualexpr
intptr_t opcode
Definition: execExpr.h:274
Datum * resvalue
Definition: execExpr.h:277
struct ExprEvalStep::@52::@54 var
union ExprEvalStep::@52 d
bool * resnull
Definition: execExpr.h:278
Definition: fmgr.h:57
PGFunction fn_addr
Definition: fmgr.h:58
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Definition: pg_list.h:51
Datum value
Definition: postgres.h:422
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_FUNCTION, ExprEvalStep::opcode, palloc0(), pg_proc_aclcheck(), 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 4113 of file execExpr.c.

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

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_FUNCTION, ExprEvalStep::opcode, palloc0(), pg_proc_aclcheck(), 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 353 of file execExpr.c.

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

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, T_ExprState, 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 513 of file execExpr.c.

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

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, T_ExprState, TupleDescAttr, and ExprState::type.

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext context 
)

Definition at line 853 of file execExpr.c.

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

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:774
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:400
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:2707
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:701
#define INDEX_MAX_KEYS
int errtableconstraint(Relation rel, const char *conname)
Definition: relcache.c:5873
bool ii_Unique
Definition: execnodes.h:175
ExprState * ii_PredicateState
Definition: execnodes.h:167
Oid * ii_ExclusionOps
Definition: execnodes.h:168
bool ii_ReadyForInserts
Definition: execnodes.h:177
List * ii_Predicate
Definition: execnodes.h:166
Form_pg_index rd_index
Definition: rel.h:188
int ri_NumIndices
Definition: execnodes.h:436
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:439
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:442

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:183
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:1984
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1909
ObjectType get_relkind_objtype(char relkind)
@ RTE_RELATION
Definition: parsenodes.h:998
RTEKind rtekind
Definition: parsenodes.h:1015

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

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

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

1568 {
1569  int i;
1570 
1571  for (i = 0; i < estate->es_range_table_size; i++)
1572  {
1573  if (estate->es_relations[i])
1574  table_close(estate->es_relations[i], NoLock);
1575  }
1576 }
#define NoLock
Definition: lockdefs.h:34
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167

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

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

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

557 {
558  if (tlist_matches_tupdesc(planstate,
559  planstate->plan->targetlist,
560  varno,
561  inputDesc))
562  {
563  planstate->ps_ProjInfo = NULL;
564  planstate->resultopsset = planstate->scanopsset;
565  planstate->resultopsfixed = planstate->scanopsfixed;
566  planstate->resultops = planstate->scanops;
567  }
568  else
569  {
570  if (!planstate->ps_ResultTupleSlot)
571  {
572  ExecInitResultSlot(planstate, &TTSOpsVirtual);
573  planstate->resultops = &TTSOpsVirtual;
574  planstate->resultopsfixed = true;
575  planstate->resultopsset = true;
576  }
577  ExecAssignProjectionInfo(planstate, inputDesc);
578  }
579 }
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:582
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:535
const TupleTableSlotOps * resultops
Definition: execnodes.h:1075
bool resultopsset
Definition: execnodes.h:1083
const TupleTableSlotOps * scanops
Definition: execnodes.h:1072
bool scanopsset
Definition: execnodes.h:1080
bool scanopsfixed
Definition: execnodes.h:1076
bool resultopsfixed
Definition: execnodes.h:1079

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

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

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

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

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
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
@ 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:1625
ItemPointerData curCtid
Definition: execnodes.h:713
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:402

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 556 of file execProcnode.c.

557 {
558  /*
559  * do nothing when we get to the end of a leaf on tree.
560  */
561  if (node == NULL)
562  return;
563 
564  /*
565  * Make sure there's enough stack available. Need to check here, in
566  * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
567  * guaranteed that ExecProcNode() is reached for all nodes.
568  */
570 
571  if (node->chgParam != NULL)
572  {
573  bms_free(node->chgParam);
574  node->chgParam = NULL;
575  }
576 
577  switch (nodeTag(node))
578  {
579  /*
580  * control nodes
581  */
582  case T_ResultState:
583  ExecEndResult((ResultState *) node);
584  break;
585 
586  case T_ProjectSetState:
588  break;
589 
590  case T_ModifyTableState:
592  break;
593 
594  case T_AppendState:
595  ExecEndAppend((AppendState *) node);
596  break;
597 
598  case T_MergeAppendState:
600  break;
601 
604  break;
605 
606  case T_BitmapAndState:
608  break;
609 
610  case T_BitmapOrState:
611  ExecEndBitmapOr((BitmapOrState *) node);
612  break;
613 
614  /*
615  * scan nodes
616  */
617  case T_SeqScanState:
618  ExecEndSeqScan((SeqScanState *) node);
619  break;
620 
621  case T_SampleScanState:
623  break;
624 
625  case T_GatherState:
626  ExecEndGather((GatherState *) node);
627  break;
628 
629  case T_GatherMergeState:
631  break;
632 
633  case T_IndexScanState:
635  break;
636 
639  break;
640 
643  break;
644 
647  break;
648 
649  case T_TidScanState:
650  ExecEndTidScan((TidScanState *) node);
651  break;
652 
653  case T_TidRangeScanState:
655  break;
656 
657  case T_SubqueryScanState:
659  break;
660 
661  case T_FunctionScanState:
663  break;
664 
667  break;
668 
669  case T_ValuesScanState:
671  break;
672 
673  case T_CteScanState:
674  ExecEndCteScan((CteScanState *) node);
675  break;
676 
679  break;
680 
683  break;
684 
685  case T_ForeignScanState:
687  break;
688 
689  case T_CustomScanState:
691  break;
692 
693  /*
694  * join nodes
695  */
696  case T_NestLoopState:
697  ExecEndNestLoop((NestLoopState *) node);
698  break;
699 
700  case T_MergeJoinState:
702  break;
703 
704  case T_HashJoinState:
705  ExecEndHashJoin((HashJoinState *) node);
706  break;
707 
708  /*
709  * materialization nodes
710  */
711  case T_MaterialState:
712  ExecEndMaterial((MaterialState *) node);
713  break;
714 
715  case T_SortState:
716  ExecEndSort((SortState *) node);
717  break;
718 
721  break;
722 
723  case T_MemoizeState:
724  ExecEndMemoize((MemoizeState *) node);
725  break;
726 
727  case T_GroupState:
728  ExecEndGroup((GroupState *) node);
729  break;
730 
731  case T_AggState:
732  ExecEndAgg((AggState *) node);
733  break;
734 
735  case T_WindowAggState:
737  break;
738 
739  case T_UniqueState:
740  ExecEndUnique((UniqueState *) node);
741  break;
742 
743  case T_HashState:
744  ExecEndHash((HashState *) node);
745  break;
746 
747  case T_SetOpState:
748  ExecEndSetOp((SetOpState *) node);
749  break;
750 
751  case T_LockRowsState:
752  ExecEndLockRows((LockRowsState *) node);
753  break;
754 
755  case T_LimitState:
756  ExecEndLimit((LimitState *) node);
757  break;
758 
759  default:
760  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
761  break;
762  }
763 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
void ExecEndAgg(AggState *node)
Definition: nodeAgg.c:4270
void ExecEndAppend(AppendState *node)
Definition: nodeAppend.c:382
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:119
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:1030
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:297
void ExecEndSubqueryScan(SubqueryScanState *node)
void ExecEndTableFuncScan(TableFuncScanState *node)
void ExecEndTidRangeScan(TidRangeScanState *node)
void ExecEndTidScan(TidScanState *node)
Definition: nodeTidscan.c:468
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:578
@ T_HashJoinState
Definition: nodes.h:135
@ T_WorkTableScanState
Definition: nodes.h:129
@ T_MergeAppendState
Definition: nodes.h:110
@ T_IndexOnlyScanState
Definition: nodes.h:118
@ T_SeqScanState
Definition: nodes.h:115
@ T_ValuesScanState
Definition: nodes.h:126
@ T_CustomScanState
Definition: nodes.h:131
@ T_HashState
Definition: nodes.h:146
@ T_TidRangeScanState
Definition: nodes.h:122
@ T_GroupState
Definition: nodes.h:140
@ T_SampleScanState
Definition: nodes.h:116
@ T_SortState
Definition: nodes.h:138
@ T_IncrementalSortState
Definition: nodes.h:139
@ T_SubqueryScanState
Definition: nodes.h:123
@ T_CteScanState
Definition: nodes.h:127
@ T_ResultState
Definition: nodes.h:106
@ T_BitmapHeapScanState
Definition: nodes.h:120
@ T_RecursiveUnionState
Definition: nodes.h:111
@ T_MaterialState
Definition: nodes.h:136
@ T_AppendState
Definition: nodes.h:109
@ T_LockRowsState
Definition: nodes.h:148
@ T_NamedTuplestoreScanState
Definition: nodes.h:128
@ T_TidScanState
Definition: nodes.h:121
@ T_ModifyTableState
Definition: nodes.h:108
@ T_AggState
Definition: nodes.h:141
@ T_ProjectSetState
Definition: nodes.h:107
@ T_GatherState
Definition: nodes.h:144
@ T_BitmapOrState
Definition: nodes.h:113
@ T_FunctionScanState
Definition: nodes.h:124
@ T_SetOpState
Definition: nodes.h:147
@ T_UniqueState
Definition: nodes.h:143
@ T_MemoizeState
Definition: nodes.h:137
@ T_MergeJoinState
Definition: nodes.h:134
@ T_BitmapAndState
Definition: nodes.h:112
@ T_WindowAggState
Definition: nodes.h:142
@ T_NestLoopState
Definition: nodes.h:133
@ T_TableFuncScanState
Definition: nodes.h:125
@ T_BitmapIndexScanState
Definition: nodes.h:119
@ T_IndexScanState
Definition: nodes.h:117
@ T_GatherMergeState
Definition: nodes.h:145
@ T_ForeignScanState
Definition: nodes.h:130
@ T_LimitState
Definition: nodes.h:149
void check_stack_depth(void)
Definition: postgres.c:3500

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(), nodeTag, T_AggState, T_AppendState, T_BitmapAndState, T_BitmapHeapScanState, T_BitmapIndexScanState, T_BitmapOrState, T_CteScanState, T_CustomScanState, T_ForeignScanState, T_FunctionScanState, T_GatherMergeState, T_GatherState, T_GroupState, T_HashJoinState, T_HashState, T_IncrementalSortState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MemoizeState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NamedTuplestoreScanState, T_NestLoopState, T_ProjectSetState, T_RecursiveUnionState, T_ResultState, T_SampleScanState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TableFuncScanState, T_TidRangeScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, and T_WorkTableScanState.

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:372
TupleTableSlot * jf_resultSlot
Definition: execnodes.h:374
AttrNumber * jf_cleanMap
Definition: execnodes.h:373
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:354

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:371

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:1718

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

2365 {
2366  if (rti > 0 && rti <= estate->es_range_table_size &&
2367  estate->es_rowmarks != NULL)
2368  {
2369  ExecRowMark *erm = estate->es_rowmarks[rti - 1];
2370 
2371  if (erm)
2372  return erm;
2373  }
2374  if (!missing_ok)
2375  elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2376  return NULL;
2377 }

References elog, ERROR, and EState::es_rowmarks.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

◆ ExecFreeExprContext()

◆ ExecGetAllUpdatedCols()

Bitmapset* ExecGetAllUpdatedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1347 of file execUtils.c.

1348 {
1349  return bms_union(ExecGetUpdatedCols(relinfo, estate),
1350  ExecGetExtraUpdatedCols(relinfo, estate));
1351 }
Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1321

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

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

◆ ExecGetAncestorResultRels()

List* ExecGetAncestorResultRels ( EState estate,
ResultRelInfo resultRelInfo 
)

Definition at line 1362 of file execMain.c.

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

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

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

1322 {
1323  /* see ExecGetInsertedCols() */
1324  if (relinfo->ri_RangeTableIndex != 0)
1325  {
1326  RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
1327 
1328  return rte->extraUpdatedCols;
1329  }
1330  else if (relinfo->ri_RootResultRelInfo)
1331  {
1332  ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
1333  RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
1334 
1335  if (relinfo->ri_RootToPartitionMap != NULL)
1337  rte->extraUpdatedCols);
1338  else
1339  return rte->extraUpdatedCols;
1340  }
1341  else
1342  return NULL;
1343 }
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:575
Bitmapset * extraUpdatedCols
Definition: parsenodes.h:1170
TupleConversionMap * ri_RootToPartitionMap
Definition: execnodes.h:539
AttrMap * attrMap
Definition: tupconvert.h:28
Bitmapset * execute_attr_map_cols(AttrMap *attrMap, Bitmapset *in_cols)
Definition: tupconvert.c:237

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

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

◆ ExecGetInsertedCols()

Bitmapset* ExecGetInsertedCols ( ResultRelInfo relinfo,
EState estate 
)

Definition at line 1256 of file execUtils.c.

1257 {
1258  /*
1259  * The columns are stored in the range table entry. If this ResultRelInfo
1260  * represents a partition routing target, and doesn't have an entry of its
1261  * own in the range table, fetch the parent's RTE and map the columns to
1262  * the order they are in the partition.
1263  */
1264  if (relinfo->ri_RangeTableIndex != 0)
1265  {
1266  RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
1267 
1268  return rte->insertedCols;
1269  }
1270  else if (relinfo->ri_RootResultRelInfo)
1271  {
1272  ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
1273  RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
1274 
1275  if (relinfo->ri_RootToPartitionMap != NULL)
1277  rte->insertedCols);
1278  else
1279  return rte->insertedCols;
1280  }
1281  else
1282  {
1283  /*
1284  * The relation isn't in the range table and it isn't a partition
1285  * routing target. This ResultRelInfo must've been created only for
1286  * firing triggers and the relation is not being inserted into. (See
1287  * ExecGetTriggerResultRel.)
1288  */
1289  return NULL;
1290  }
1291 }
Bitmapset * insertedCols
Definition: parsenodes.h:1168

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

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:381

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

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

500 {
501  if (planstate->resultopsset && planstate->resultops)
502  {
503  if (isfixed)
504  *isfixed = planstate->resultopsfixed;
505  return planstate->resultops;
506  }
507 
508  if (isfixed)
509  {
510  if (planstate->resultopsset)
511  *isfixed = planstate->resultopsfixed;
512  else if (planstate->ps_ResultTupleSlot)
513  *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
514  else
515  *isfixed = false;
516  }
517 
518  if (!planstate->ps_ResultTupleSlot)
519  return &TTSOpsVirtual;
520 
521  return planstate->ps_ResultTupleSlot->tts_ops;
522 }
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 1210 of file execUtils.c.

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

◆ ExecGetTriggerNewSlot()

TupleTableSlot* ExecGetTriggerNewSlot ( EState estate,
ResultRelInfo relInfo 
)

Definition at line 1188 of file execUtils.c.

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

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 
)

Definition at line 1166 of file execUtils.c.

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

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