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

Go to the source code of this file.

Data Structures

struct  TupOutputState
 

Macros

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

Typedefs

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

Functions

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

Variables

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

Macro Definition Documentation

◆ do_text_output_oneline

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

Definition at line 540 of file executor.h.

◆ EvalPlanQualSetSlot

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

Definition at line 247 of file executor.h.

◆ EXEC_FLAG_BACKWARD

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

Definition at line 68 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_GENERIC

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

Definition at line 66 of file executor.h.

◆ EXEC_FLAG_EXPLAIN_ONLY

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

Definition at line 65 of file executor.h.

◆ EXEC_FLAG_MARK

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

Definition at line 69 of file executor.h.

◆ EXEC_FLAG_REWIND

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

Definition at line 67 of file executor.h.

◆ EXEC_FLAG_SKIP_TRIGGERS

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

Definition at line 70 of file executor.h.

◆ EXEC_FLAG_WITH_NO_DATA

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

Definition at line 71 of file executor.h.

◆ GetPerTupleExprContext

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

Definition at line 568 of file executor.h.

◆ GetPerTupleMemoryContext

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

Definition at line 573 of file executor.h.

◆ ResetExprContext

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

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

Typedef Documentation

◆ ExecScanAccessMtd

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

Definition at line 491 of file executor.h.

◆ ExecScanRecheckMtd

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

Definition at line 492 of file executor.h.

◆ ExecutorCheckPerms_hook_type

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

Definition at line 93 of file executor.h.

◆ ExecutorEnd_hook_type

typedef void(* ExecutorEnd_hook_type) (QueryDesc *queryDesc)

Definition at line 89 of file executor.h.

◆ ExecutorFinish_hook_type

typedef void(* ExecutorFinish_hook_type) (QueryDesc *queryDesc)

Definition at line 85 of file executor.h.

◆ ExecutorRun_hook_type

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

Definition at line 79 of file executor.h.

◆ ExecutorStart_hook_type

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

Definition at line 75 of file executor.h.

◆ TupOutputState

Function Documentation

◆ begin_tup_output_tupdesc()

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

Definition at line 2342 of file execTuples.c.

2345 {
2346  TupOutputState *tstate;
2347 
2348  tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2349 
2350  tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2351  tstate->dest = dest;
2352 
2353  tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2354 
2355  return tstate;
2356 }
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1325
void * palloc(Size size)
Definition: mcxt.c:1317
@ CMD_SELECT
Definition: nodes.h:265
TupleTableSlot * slot
Definition: executor.h:524
DestReceiver * dest
Definition: executor.h:525
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121

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

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

◆ BuildTupleHashTable()

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

Definition at line 264 of file execGrouping.c.

274 {
275  return BuildTupleHashTableExt(parent,
276  inputDesc,
277  numCols, keyColIdx,
278  eqfuncoids,
279  hashfunctions,
280  collations,
281  nbuckets, additionalsize,
282  tablecxt,
283  tablecxt,
284  tempcxt,
285  use_variable_hash_iv);
286 }
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:155

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

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

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

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

◆ check_exclusion_constraint()

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

Definition at line 950 of file execIndexing.c.

955 {
956  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
957  values, isnull,
958  estate, newIndex,
959  CEOUC_WAIT, false, NULL);
960 }
static Datum values[MAXATTR]
Definition: bootstrap.c:151
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool violationOK, ItemPointer conflictTid)
Definition: execIndexing.c:698
@ CEOUC_WAIT
Definition: execIndexing.c:124
Definition: type.h:96

References CEOUC_WAIT, check_exclusion_or_unique_constraint(), and values.

Referenced by IndexCheckExclusion().

◆ CheckCmdReplicaIdentity()

void CheckCmdReplicaIdentity ( Relation  rel,
CmdType  cmd 
)

Definition at line 761 of file execReplication.c.

762 {
763  PublicationDesc pubdesc;
764 
765  /*
766  * Skip checking the replica identity for partitioned tables, because the
767  * operations are actually performed on the leaf partitions.
768  */
769  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
770  return;
771 
772  /* We only need to do checks for UPDATE and DELETE. */
773  if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
774  return;
775 
776  /*
777  * It is only safe to execute UPDATE/DELETE if the relation does not
778  * publish UPDATEs or DELETEs, or all the following conditions are
779  * satisfied:
780  *
781  * 1. All columns, referenced in the row filters from publications which
782  * the relation is in, are valid - i.e. when all referenced columns are
783  * part of REPLICA IDENTITY.
784  *
785  * 2. All columns, referenced in the column lists are valid - i.e. when
786  * all columns referenced in the REPLICA IDENTITY are covered by the
787  * column list.
788  *
789  * 3. All generated columns in REPLICA IDENTITY of the relation, are valid
790  * - i.e. when all these generated columns are published.
791  *
792  * XXX We could optimize it by first checking whether any of the
793  * publications have a row filter or column list for this relation, or if
794  * the relation contains a generated column. If none of these exist and
795  * the relation has replica identity then we can avoid building the
796  * descriptor but as this happens only one time it doesn't seem worth the
797  * additional complexity.
798  */
799  RelationBuildPublicationDesc(rel, &pubdesc);
800  if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
801  ereport(ERROR,
802  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
803  errmsg("cannot update table \"%s\"",
805  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
806  else if (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
807  ereport(ERROR,
808  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
809  errmsg("cannot update table \"%s\"",
811  errdetail("Column list used by the publication does not cover the replica identity.")));
812  else if (cmd == CMD_UPDATE && !pubdesc.gencols_valid_for_update)
813  ereport(ERROR,
814  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
815  errmsg("cannot update table \"%s\"",
817  errdetail("Replica identity must not contain unpublished generated columns.")));
818  else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
819  ereport(ERROR,
820  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
821  errmsg("cannot delete from table \"%s\"",
823  errdetail("Column used in the publication WHERE expression is not part of the replica identity.")));
824  else if (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
825  ereport(ERROR,
826  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
827  errmsg("cannot delete from table \"%s\"",
829  errdetail("Column list used by the publication does not cover the replica identity.")));
830  else if (cmd == CMD_DELETE && !pubdesc.gencols_valid_for_delete)
831  ereport(ERROR,
832  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
833  errmsg("cannot delete from table \"%s\"",
835  errdetail("Replica identity must not contain unpublished generated columns.")));
836 
837  /* If relation has replica identity we are always good. */
839  return;
840 
841  /* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */
842  if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
843  return;
844 
845  /*
846  * This is UPDATE/DELETE and there is no replica identity.
847  *
848  * Check if the table publishes UPDATES or DELETES.
849  */
850  if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
851  ereport(ERROR,
852  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
853  errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
855  errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
856  else if (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
857  ereport(ERROR,
858  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
859  errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
861  errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
862 }
#define OidIsValid(objectId)
Definition: c.h:729
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
#define RelationGetRelationName(relation)
Definition: rel.h:539
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Definition: relcache.c:5724
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:5002
PublicationActions pubactions
bool gencols_valid_for_update
bool cols_valid_for_update
bool gencols_valid_for_delete
Form_pg_class rd_rel
Definition: rel.h:111

References CMD_DELETE, CMD_UPDATE, PublicationDesc::cols_valid_for_delete, PublicationDesc::cols_valid_for_update, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, PublicationDesc::gencols_valid_for_delete, PublicationDesc::gencols_valid_for_update, 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 871 of file execReplication.c.

873 {
874  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
875  ereport(ERROR,
876  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
877  errmsg("cannot use relation \"%s.%s\" as logical replication target",
878  nspname, relname),
880 }
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
NameData relname
Definition: pg_class.h:38

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

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

◆ CheckValidResultRel()

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

Definition at line 1026 of file execMain.c.

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

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

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

◆ CreateExecutorState()

EState* CreateExecutorState ( void  )

Definition at line 88 of file execUtils.c.

89 {
90  EState *estate;
91  MemoryContext qcontext;
92  MemoryContext oldcontext;
93 
94  /*
95  * Create the per-query context for this Executor run.
96  */
98  "ExecutorState",
100 
101  /*
102  * Make the EState node within the per-query context. This way, we don't
103  * need a separate pfree() operation for it at shutdown.
104  */
105  oldcontext = MemoryContextSwitchTo(qcontext);
106 
107  estate = makeNode(EState);
108 
109  /*
110  * Initialize all fields of the Executor State structure
111  */
113  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
114  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
115  estate->es_range_table = NIL;
116  estate->es_range_table_size = 0;
117  estate->es_relations = NULL;
118  estate->es_rowmarks = NULL;
119  estate->es_rteperminfos = NIL;
120  estate->es_plannedstmt = NULL;
121 
122  estate->es_junkFilter = NULL;
123 
124  estate->es_output_cid = (CommandId) 0;
125 
126  estate->es_result_relations = NULL;
129  estate->es_trig_target_relations = NIL;
130 
133 
134  estate->es_param_list_info = NULL;
135  estate->es_param_exec_vals = NULL;
136 
137  estate->es_queryEnv = NULL;
138 
139  estate->es_query_cxt = qcontext;
140 
141  estate->es_tupleTable = NIL;
142 
143  estate->es_processed = 0;
144  estate->es_total_processed = 0;
145 
146  estate->es_top_eflags = 0;
147  estate->es_instrument = 0;
148  estate->es_finished = false;
149 
150  estate->es_exprcontexts = NIL;
151 
152  estate->es_subplanstates = NIL;
153 
154  estate->es_auxmodifytables = NIL;
155 
156  estate->es_per_tuple_exprcontext = NULL;
157 
158  estate->es_sourceText = NULL;
159 
160  estate->es_use_parallel_mode = false;
161  estate->es_parallel_workers_to_launch = 0;
162  estate->es_parallel_workers_launched = 0;
163 
164  estate->es_jit_flags = 0;
165  estate->es_jit = NULL;
166 
167  /*
168  * Return the executor state structure
169  */
170  MemoryContextSwitchTo(oldcontext);
171 
172  return estate;
173 }
uint32 CommandId
Definition: c.h:620
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define makeNode(_type_)
Definition: nodes.h:155
#define NIL
Definition: pg_list.h:68
@ ForwardScanDirection
Definition: sdir.h:28
#define InvalidSnapshot
Definition: snapshot.h:119
uint64 es_processed
Definition: execnodes.h:679
struct ExecRowMark ** es_rowmarks
Definition: execnodes.h:638
int es_parallel_workers_to_launch
Definition: execnodes.h:711
List * es_tuple_routing_result_relations
Definition: execnodes.h:663
int es_top_eflags
Definition: execnodes.h:684
struct JitContext * es_jit
Definition: execnodes.h:729
int es_instrument
Definition: execnodes.h:685
PlannedStmt * es_plannedstmt
Definition: execnodes.h:641
QueryEnvironment * es_queryEnv
Definition: execnodes.h:672
ResultRelInfo ** es_result_relations
Definition: execnodes.h:650
ParamExecData * es_param_exec_vals
Definition: execnodes.h:670
uint64 es_total_processed
Definition: execnodes.h:681
List * es_range_table
Definition: execnodes.h:634
List * es_rteperminfos
Definition: execnodes.h:640
List * es_exprcontexts
Definition: execnodes.h:688
ParamListInfo es_param_list_info
Definition: execnodes.h:669
bool es_finished
Definition: execnodes.h:686
List * es_insert_pending_result_relations
Definition: execnodes.h:736
MemoryContext es_query_cxt
Definition: execnodes.h:675
List * es_tupleTable
Definition: execnodes.h:677
ScanDirection es_direction
Definition: execnodes.h:631
List * es_trig_target_relations
Definition: execnodes.h:666
int es_jit_flags
Definition: execnodes.h:728
List * es_opened_result_relations
Definition: execnodes.h:653
bool es_use_parallel_mode
Definition: execnodes.h:709
Relation * es_relations
Definition: execnodes.h:636
List * es_subplanstates
Definition: execnodes.h:690
ExprContext * es_per_tuple_exprcontext
Definition: execnodes.h:699
int es_parallel_workers_launched
Definition: execnodes.h:713
CommandId es_output_cid
Definition: execnodes.h:647
Index es_range_table_size
Definition: execnodes.h:635
List * es_insert_pending_modifytables
Definition: execnodes.h:737
const char * es_sourceText
Definition: execnodes.h:642
Snapshot es_snapshot
Definition: execnodes.h:632
List * es_auxmodifytables
Definition: execnodes.h:692
JunkFilter * es_junkFilter
Definition: execnodes.h:644
Snapshot es_crosscheck_snapshot
Definition: execnodes.h:633

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

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

◆ CreateExprContext()

ExprContext* CreateExprContext ( EState estate)

Definition at line 306 of file execUtils.c.

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

References ALLOCSET_DEFAULT_SIZES, and CreateExprContextInternal().

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

◆ CreateStandaloneExprContext()

ExprContext* CreateStandaloneExprContext ( void  )

Definition at line 357 of file execUtils.c.

358 {
359  ExprContext *econtext;
360 
361  /* Create the ExprContext node within the caller's memory context */
362  econtext = makeNode(ExprContext);
363 
364  /* Initialize fields of ExprContext */
365  econtext->ecxt_scantuple = NULL;
366  econtext->ecxt_innertuple = NULL;
367  econtext->ecxt_outertuple = NULL;
368 
370 
371  /*
372  * Create working memory for expression evaluation in this context.
373  */
374  econtext->ecxt_per_tuple_memory =
376  "ExprContext",
378 
379  econtext->ecxt_param_exec_vals = NULL;
380  econtext->ecxt_param_list_info = NULL;
381 
382  econtext->ecxt_aggvalues = NULL;
383  econtext->ecxt_aggnulls = NULL;
384 
385  econtext->caseValue_datum = (Datum) 0;
386  econtext->caseValue_isNull = true;
387 
388  econtext->domainValue_datum = (Datum) 0;
389  econtext->domainValue_isNull = true;
390 
391  econtext->ecxt_estate = NULL;
392 
393  econtext->ecxt_callbacks = NULL;
394 
395  return econtext;
396 }
uintptr_t Datum
Definition: postgres.h:64
Datum domainValue_datum
Definition: execnodes.h:289
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:270
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:266
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:260
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:269
Datum * ecxt_aggvalues
Definition: execnodes.h:277
bool caseValue_isNull
Definition: execnodes.h:285
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:258
Datum caseValue_datum
Definition: execnodes.h:283
bool * ecxt_aggnulls
Definition: execnodes.h:279
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:265
ExprContext_CB * ecxt_callbacks
Definition: execnodes.h:297
bool domainValue_isNull
Definition: execnodes.h:291
struct EState * ecxt_estate
Definition: execnodes.h:294
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:262

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

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

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

Referenced by ExecInitAgg().

◆ do_text_output_multiline()

void do_text_output_multiline ( TupOutputState tstate,
const char *  txt 
)

Definition at line 2390 of file execTuples.c.

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

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

Referenced by ExplainQuery().

◆ do_tup_output()

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

Definition at line 2362 of file execTuples.c.

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

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

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

◆ end_tup_output()

void end_tup_output ( TupOutputState tstate)

Definition at line 2420 of file execTuples.c.

2421 {
2422  tstate->dest->rShutdown(tstate->dest);
2423  /* note that destroying the dest is not ours to do */
2425  pfree(tstate);
2426 }
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1341
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124

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

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

◆ EvalPlanQual()

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

Definition at line 2479 of file execMain.c.

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

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

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

◆ EvalPlanQualBegin()

void EvalPlanQualBegin ( EPQState epqstate)

Definition at line 2760 of file execMain.c.

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

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

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

◆ EvalPlanQualEnd()

void EvalPlanQualEnd ( EPQState epqstate)

Definition at line 2991 of file execMain.c.

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

References EState::es_query_cxt, EState::es_range_table_size, EState::es_subplanstates, EState::es_tupleTable, ExecCloseResultRelations(), ExecEndNode(), ExecResetTupleTable(), FreeExecutorState(), lfirst, MemoryContextSwitchTo(), NIL, EPQState::origslot, EPQState::parentestate, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_blocked, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::relsubs_slot, and EPQState::tuple_table.

Referenced by apply_handle_delete_internal(), apply_handle_tuple_routing(), apply_handle_update_internal(), EvalPlanQualSetPlan(), ExecEndLockRows(), ExecEndModifyTable(), and ExecLockRows().

◆ EvalPlanQualFetchRowMark()

bool EvalPlanQualFetchRowMark ( EPQState epqstate,
Index  rti,
TupleTableSlot slot 
)

Definition at line 2635 of file execMain.c.

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

References Assert, ExecAuxRowMark::ctidAttNo, DatumGetObjectId(), DatumGetPointer(), elog, ereport, errcode(), errmsg(), ERROR, ExecGetJunkAttribute(), ExecStoreHeapTupleDatum(), GetFdwRoutineForRelation(), ExecRowMark::markType, OidIsValid, EPQState::origslot, ExecRowMark::prti, RelationData::rd_rel, EPQState::recheckestate, FdwRoutine::RefetchForeignRow, ExecRowMark::relation, RelationGetRelationName, ExecRowMark::relid, EPQState::relsubs_rowmark, ROW_MARK_COPY, ROW_MARK_REFERENCE, ExecAuxRowMark::rowmark, RowMarkRequiresRowShareLock, ExecRowMark::rti, SnapshotAny, table_tuple_fetch_row_version(), ExecAuxRowMark::toidAttNo, TupIsNull, and ExecAuxRowMark::wholeAttNo.

Referenced by ExecScanFetch().

◆ EvalPlanQualInit()

void EvalPlanQualInit ( EPQState epqstate,
EState parentestate,
Plan subplan,
List auxrowmarks,
int  epqParam,
List resultRelations 
)

Definition at line 2548 of file execMain.c.

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

References EPQState::arowMarks, EPQState::epqParam, EState::es_range_table_size, NIL, EPQState::origslot, palloc0(), EPQState::parentestate, EPQState::plan, EPQState::recheckestate, EPQState::recheckplanstate, EPQState::relsubs_blocked, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::relsubs_slot, EPQState::resultRelations, and EPQState::tuple_table.

Referenced by apply_handle_delete_internal(), apply_handle_tuple_routing(), apply_handle_update_internal(), ExecInitLockRows(), and ExecInitModifyTable().

◆ EvalPlanQualNext()

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate)

Definition at line 2744 of file execMain.c.

2745 {
2746  MemoryContext oldcontext;
2747  TupleTableSlot *slot;
2748 
2749  oldcontext = MemoryContextSwitchTo(epqstate->recheckestate->es_query_cxt);
2750  slot = ExecProcNode(epqstate->recheckplanstate);
2751  MemoryContextSwitchTo(oldcontext);
2752 
2753  return slot;
2754 }
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:272

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

2591 {
2592  /* If we have a live EPQ query, shut it down */
2593  EvalPlanQualEnd(epqstate);
2594  /* And set/change the plan pointer */
2595  epqstate->plan = subplan;
2596  /* The rowmarks depend on the plan, too */
2597  epqstate->arowMarks = auxrowmarks;
2598 }
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:2991

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

Referenced by ExecInitModifyTable().

◆ EvalPlanQualSlot()

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

Definition at line 2607 of file execMain.c.

2609 {
2610  TupleTableSlot **slot;
2611 
2612  Assert(relation);
2613  Assert(rti > 0 && rti <= epqstate->parentestate->es_range_table_size);
2614  slot = &epqstate->relsubs_slot[rti - 1];
2615 
2616  if (*slot == NULL)
2617  {
2618  MemoryContext oldcontext;
2619 
2620  oldcontext = MemoryContextSwitchTo(epqstate->parentestate->es_query_cxt);
2621  *slot = table_slot_create(relation, &epqstate->tuple_table);
2622  MemoryContextSwitchTo(oldcontext);
2623  }
2624 
2625  return *slot;
2626 }
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
Definition: tableam.c:91

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

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

◆ exec_rt_fetch()

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

◆ ExecAssignExprContext()

◆ ExecAssignProjectionInfo()

void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)

Definition at line 540 of file execUtils.c.

542 {
543  planstate->ps_ProjInfo =
545  planstate->ps_ExprContext,
546  planstate->ps_ResultTupleSlot,
547  planstate,
548  inputDesc);
549 }
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:365
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1164
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1166
List * targetlist
Definition: plannodes.h:153

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

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

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)

◆ ExecAssignScanType()

void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)

Definition at line 649 of file execUtils.c.

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

References ExecSetSlotDescriptor(), and ScanState::ss_ScanTupleSlot.

Referenced by ExecWorkTableScan().

◆ ExecBuildAggTrans()

ExprState* ExecBuildAggTrans ( AggState aggstate,
struct AggStatePerPhaseData phase,
bool  doSort,
bool  doHash,
bool  nullcheck 
)

◆ ExecBuildAuxRowMark()

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 2409 of file execMain.c.

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

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

4328 {
4330  ExprEvalStep scratch = {0};
4331  int maxatt = -1;
4332  List *adjust_jumps = NIL;
4333  ListCell *lc;
4334 
4335  /*
4336  * When no columns are actually compared, the result's always true. See
4337  * special case in ExecQual().
4338  */
4339  if (numCols == 0)
4340  return NULL;
4341 
4342  state->expr = NULL;
4343  state->flags = EEO_FLAG_IS_QUAL;
4344  state->parent = parent;
4345 
4346  scratch.resvalue = &state->resvalue;
4347  scratch.resnull = &state->resnull;
4348 
4349  /* compute max needed attribute */
4350  for (int natt = 0; natt < numCols; natt++)
4351  {
4352  int attno = keyColIdx[natt];
4353 
4354  if (attno > maxatt)
4355  maxatt = attno;
4356  }
4357  Assert(maxatt >= 0);
4358 
4359  /* push deform steps */
4360  scratch.opcode = EEOP_INNER_FETCHSOME;
4361  scratch.d.fetch.last_var = maxatt;
4362  scratch.d.fetch.fixed = false;
4363  scratch.d.fetch.known_desc = ldesc;
4364  scratch.d.fetch.kind = lops;
4365  if (ExecComputeSlotInfo(state, &scratch))
4366  ExprEvalPushStep(state, &scratch);
4367 
4368  scratch.opcode = EEOP_OUTER_FETCHSOME;
4369  scratch.d.fetch.last_var = maxatt;
4370  scratch.d.fetch.fixed = false;
4371  scratch.d.fetch.known_desc = rdesc;
4372  scratch.d.fetch.kind = rops;
4373  if (ExecComputeSlotInfo(state, &scratch))
4374  ExprEvalPushStep(state, &scratch);
4375 
4376  /*
4377  * Start comparing at the last field (least significant sort key). That's
4378  * the most likely to be different if we are dealing with sorted input.
4379  */
4380  for (int natt = numCols; --natt >= 0;)
4381  {
4382  int attno = keyColIdx[natt];
4383  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
4384  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
4385  Oid foid = eqfunctions[natt];
4386  Oid collid = collations[natt];
4387  FmgrInfo *finfo;
4388  FunctionCallInfo fcinfo;
4389  AclResult aclresult;
4390 
4391  /* Check permission to call function */
4392  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4393  if (aclresult != ACLCHECK_OK)
4394  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4395 
4397 
4398  /* Set up the primary fmgr lookup information */
4399  finfo = palloc0(sizeof(FmgrInfo));
4400  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4401  fmgr_info(foid, finfo);
4402  fmgr_info_set_expr(NULL, finfo);
4403  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4404  collid, NULL, NULL);
4405 
4406  /* left arg */
4407  scratch.opcode = EEOP_INNER_VAR;
4408  scratch.d.var.attnum = attno - 1;
4409  scratch.d.var.vartype = latt->atttypid;
4410  scratch.resvalue = &fcinfo->args[0].value;
4411  scratch.resnull = &fcinfo->args[0].isnull;
4412  ExprEvalPushStep(state, &scratch);
4413 
4414  /* right arg */
4415  scratch.opcode = EEOP_OUTER_VAR;
4416  scratch.d.var.attnum = attno - 1;
4417  scratch.d.var.vartype = ratt->atttypid;
4418  scratch.resvalue = &fcinfo->args[1].value;
4419  scratch.resnull = &fcinfo->args[1].isnull;
4420  ExprEvalPushStep(state, &scratch);
4421 
4422  /* evaluate distinctness */
4423  scratch.opcode = EEOP_NOT_DISTINCT;
4424  scratch.d.func.finfo = finfo;
4425  scratch.d.func.fcinfo_data = fcinfo;
4426  scratch.d.func.fn_addr = finfo->fn_addr;
4427  scratch.d.func.nargs = 2;
4428  scratch.resvalue = &state->resvalue;
4429  scratch.resnull = &state->resnull;
4430  ExprEvalPushStep(state, &scratch);
4431 
4432  /* then emit EEOP_QUAL to detect if result is false (or null) */
4433  scratch.opcode = EEOP_QUAL;
4434  scratch.d.qualexpr.jumpdone = -1;
4435  scratch.resvalue = &state->resvalue;
4436  scratch.resnull = &state->resnull;
4437  ExprEvalPushStep(state, &scratch);
4438  adjust_jumps = lappend_int(adjust_jumps,
4439  state->steps_len - 1);
4440  }
4441 
4442  /* adjust jump targets */
4443  foreach(lc, adjust_jumps)
4444  {
4445  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4446 
4447  Assert(as->opcode == EEOP_QUAL);
4448  Assert(as->d.qualexpr.jumpdone == -1);
4449  as->d.qualexpr.jumpdone = state->steps_len;
4450  }
4451 
4452  scratch.resvalue = NULL;
4453  scratch.resnull = NULL;
4454  scratch.opcode = EEOP_DONE;
4455  ExprEvalPushStep(state, &scratch);
4456 
4458 
4459  return state;
4460 }
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2622
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3810
Oid collid
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2592
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2932
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:880
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:176
@ EEOP_INNER_VAR
Definition: execExpr.h:77
@ EEOP_DONE
Definition: execExpr.h:69
@ EEOP_QUAL
Definition: execExpr.h:135
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:72
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:73
@ EEOP_OUTER_VAR
Definition: execExpr.h:78
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:76
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
List * lappend_int(List *list, int datum)
Definition: list.c:357
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1608
Oid GetUserId(void)
Definition: miscinit.c:524
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
@ OBJECT_FUNCTION
Definition: parsenodes.h:2287
#define ACL_EXECUTE
Definition: parsenodes.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define lfirst_int(lc)
Definition: pg_list.h:173
struct ExprEvalStep::@55::@57 var
struct ExprEvalStep::@55::@64 qualexpr
intptr_t opcode
Definition: execExpr.h:290
struct ExprEvalStep::@55::@62 func
Datum * resvalue
Definition: execExpr.h:293
union ExprEvalStep::@55 d
bool * resnull
Definition: execExpr.h:294
struct ExprEvalStep::@55::@56 fetch
Definition: fmgr.h:57
PGFunction fn_addr
Definition: fmgr.h:58
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Definition: pg_list.h:54
Datum value
Definition: postgres.h:75
bool isnull
Definition: postgres.h:77
Definition: regguts.h:323
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

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

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

◆ ExecBuildHash32Expr()

ExprState* ExecBuildHash32Expr ( TupleDesc  desc,
const TupleTableSlotOps ops,
const Oid hashfunc_oids,
const List collations,
const List hash_exprs,
const bool *  opstrict,
PlanState parent,
uint32  init_value,
bool  keep_nulls 
)

Definition at line 4156 of file execExpr.c.

4160 {
4162  ExprEvalStep scratch = {0};
4163  NullableDatum *iresult = NULL;
4164  List *adjust_jumps = NIL;
4165  ListCell *lc;
4166  ListCell *lc2;
4167  intptr_t strict_opcode;
4168  intptr_t opcode;
4169  int num_exprs = list_length(hash_exprs);
4170 
4171  Assert(num_exprs == list_length(collations));
4172 
4173  state->parent = parent;
4174 
4175  /* Insert setup steps as needed. */
4176  ExecCreateExprSetupSteps(state, (Node *) hash_exprs);
4177 
4178  /*
4179  * Make a place to store intermediate hash values between subsequent
4180  * hashing of individual expressions. We only need this if there is more
4181  * than one expression to hash or an initial value plus one expression.
4182  */
4183  if ((int64) num_exprs + (init_value != 0) > 1)
4184  iresult = palloc(sizeof(NullableDatum));
4185 
4186  if (init_value == 0)
4187  {
4188  /*
4189  * No initial value, so we can assign the result of the hash function
4190  * for the first hash_expr without having to concern ourselves with
4191  * combining the result with any initial value.
4192  */
4193  strict_opcode = EEOP_HASHDATUM_FIRST_STRICT;
4194  opcode = EEOP_HASHDATUM_FIRST;
4195  }
4196  else
4197  {
4198  /*
4199  * Set up operation to set the initial value. Normally we store this
4200  * in the intermediate hash value location, but if there are no exprs
4201  * to hash, store it in the ExprState's result field.
4202  */
4204  scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4205  scratch.resvalue = num_exprs > 0 ? &iresult->value : &state->resvalue;
4206  scratch.resnull = num_exprs > 0 ? &iresult->isnull : &state->resnull;
4207 
4208  ExprEvalPushStep(state, &scratch);
4209 
4210  /*
4211  * When using an initial value use the NEXT32/NEXT32_STRICT ops as the
4212  * FIRST/FIRST_STRICT ops would overwrite the stored initial value.
4213  */
4214  strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT;
4215  opcode = EEOP_HASHDATUM_NEXT32;
4216  }
4217 
4218  forboth(lc, hash_exprs, lc2, collations)
4219  {
4220  Expr *expr = (Expr *) lfirst(lc);
4221  FmgrInfo *finfo;
4222  FunctionCallInfo fcinfo;
4223  int i = foreach_current_index(lc);
4224  Oid funcid;
4225  Oid inputcollid = lfirst_oid(lc2);
4226 
4227  funcid = hashfunc_oids[i];
4228 
4229  /* Allocate hash function lookup data. */
4230  finfo = palloc0(sizeof(FmgrInfo));
4231  fcinfo = palloc0(SizeForFunctionCallInfo(1));
4232 
4233  fmgr_info(funcid, finfo);
4234 
4235  /*
4236  * Build the steps to evaluate the hash function's argument have it so
4237  * the value of that is stored in the 0th argument of the hash func.
4238  */
4239  ExecInitExprRec(expr,
4240  state,
4241  &fcinfo->args[0].value,
4242  &fcinfo->args[0].isnull);
4243 
4244  if (i == num_exprs - 1)
4245  {
4246  /* the result for hashing the final expr is stored in the state */
4247  scratch.resvalue = &state->resvalue;
4248  scratch.resnull = &state->resnull;
4249  }
4250  else
4251  {
4252  Assert(iresult != NULL);
4253 
4254  /* intermediate values are stored in an intermediate result */
4255  scratch.resvalue = &iresult->value;
4256  scratch.resnull = &iresult->isnull;
4257  }
4258 
4259  /*
4260  * NEXT32 opcodes need to look at the intermediate result. We might
4261  * as well just set this for all ops. FIRSTs won't look at it.
4262  */
4263  scratch.d.hashdatum.iresult = iresult;
4264 
4265  /* Initialize function call parameter structure too */
4266  InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4267 
4268  scratch.d.hashdatum.finfo = finfo;
4269  scratch.d.hashdatum.fcinfo_data = fcinfo;
4270  scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4271 
4272  scratch.opcode = opstrict[i] && !keep_nulls ? strict_opcode : opcode;
4273  scratch.d.hashdatum.jumpdone = -1;
4274 
4275  ExprEvalPushStep(state, &scratch);
4276  adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1);
4277 
4278  /*
4279  * For subsequent keys we must combine the hash value with the
4280  * previous hashes.
4281  */
4282  strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT;
4283  opcode = EEOP_HASHDATUM_NEXT32;
4284  }
4285 
4286  /* adjust jump targets */
4287  foreach(lc, adjust_jumps)
4288  {
4289  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4290 
4293  as->opcode == EEOP_HASHDATUM_NEXT32 ||
4295  Assert(as->d.hashdatum.jumpdone == -1);
4296  as->d.hashdatum.jumpdone = state->steps_len;
4297  }
4298 
4299  scratch.resvalue = NULL;
4300  scratch.resnull = NULL;
4301  scratch.opcode = EEOP_DONE;
4302  ExprEvalPushStep(state, &scratch);
4303 
4305 
4306  return state;
4307 }
int64_t int64
Definition: c.h:482
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:897
static void ExecCreateExprSetupSteps(ExprState *state, Node *node)
Definition: execExpr.c:2787
@ EEOP_HASHDATUM_NEXT32_STRICT
Definition: execExpr.h:243
@ EEOP_HASHDATUM_FIRST_STRICT
Definition: execExpr.h:241
@ EEOP_HASHDATUM_NEXT32
Definition: execExpr.h:242
@ EEOP_HASHDATUM_FIRST
Definition: execExpr.h:240
@ EEOP_HASHDATUM_SET_INITVAL
Definition: execExpr.h:239
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define foreach_current_index(var_or_cell)
Definition: pg_list.h:403
#define lfirst_oid(lc)
Definition: pg_list.h:174
static Datum UInt32GetDatum(uint32 X)
Definition: postgres.h:232
struct ExprEvalStep::@55::@86 hashdatum
struct ExprEvalStep::@55::@85 hashdatum_initvalue
Definition: nodes.h:129

References FunctionCallInfoBaseData::args, Assert, ExprEvalStep::d, EEOP_DONE, EEOP_HASHDATUM_FIRST, EEOP_HASHDATUM_FIRST_STRICT, EEOP_HASHDATUM_NEXT32, EEOP_HASHDATUM_NEXT32_STRICT, EEOP_HASHDATUM_SET_INITVAL, ExecCreateExprSetupSteps(), ExecInitExprRec(), ExecReadyExpr(), ExprEvalPushStep(), fmgr_info(), FmgrInfo::fn_addr, forboth, foreach_current_index, ExprEvalStep::hashdatum, ExprEvalStep::hashdatum_initvalue, i, InitFunctionCallInfoData, NullableDatum::isnull, lappend_int(), lfirst, lfirst_int, lfirst_oid, list_length(), makeNode, NIL, ExprEvalStep::opcode, palloc(), palloc0(), ExprEvalStep::resnull, ExprEvalStep::resvalue, SizeForFunctionCallInfo, UInt32GetDatum(), and NullableDatum::value.

Referenced by ExecInitHashJoin().

◆ ExecBuildHash32FromAttrs()

ExprState* ExecBuildHash32FromAttrs ( TupleDesc  desc,
const TupleTableSlotOps ops,
FmgrInfo hashfunctions,
Oid collations,
int  numCols,
AttrNumber keyColIdx,
PlanState parent,
uint32  init_value 
)

Definition at line 3998 of file execExpr.c.

4002 {
4004  ExprEvalStep scratch = {0};
4005  NullableDatum *iresult = NULL;
4006  intptr_t opcode;
4007  AttrNumber last_attnum = 0;
4008 
4009  Assert(numCols >= 0);
4010 
4011  state->parent = parent;
4012 
4013  /*
4014  * Make a place to store intermediate hash values between subsequent
4015  * hashing of individual columns. We only need this if there is more than
4016  * one column to hash or an initial value plus one column.
4017  */
4018  if ((int64) numCols + (init_value != 0) > 1)
4019  iresult = palloc(sizeof(NullableDatum));
4020 
4021  /* find the highest attnum so we deform the tuple to that point */
4022  for (int i = 0; i < numCols; i++)
4023  last_attnum = Max(last_attnum, keyColIdx[i]);
4024 
4025  scratch.opcode = EEOP_INNER_FETCHSOME;
4026  scratch.d.fetch.last_var = last_attnum;
4027  scratch.d.fetch.fixed = false;
4028  scratch.d.fetch.kind = ops;
4029  scratch.d.fetch.known_desc = desc;
4030  if (ExecComputeSlotInfo(state, &scratch))
4031  ExprEvalPushStep(state, &scratch);
4032 
4033  if (init_value == 0)
4034  {
4035  /*
4036  * No initial value, so we can assign the result of the hash function
4037  * for the first attribute without having to concern ourselves with
4038  * combining the result with any initial value.
4039  */
4040  opcode = EEOP_HASHDATUM_FIRST;
4041  }
4042  else
4043  {
4044  /*
4045  * Set up operation to set the initial value. Normally we store this
4046  * in the intermediate hash value location, but if there are no
4047  * columns to hash, store it in the ExprState's result field.
4048  */
4050  scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4051  scratch.resvalue = numCols > 0 ? &iresult->value : &state->resvalue;
4052  scratch.resnull = numCols > 0 ? &iresult->isnull : &state->resnull;
4053 
4054  ExprEvalPushStep(state, &scratch);
4055 
4056  /*
4057  * When using an initial value use the NEXT32 ops as the FIRST ops
4058  * would overwrite the stored initial value.
4059  */
4060  opcode = EEOP_HASHDATUM_NEXT32;
4061  }
4062 
4063  for (int i = 0; i < numCols; i++)
4064  {
4065  FmgrInfo *finfo;
4066  FunctionCallInfo fcinfo;
4067  Oid inputcollid = collations[i];
4068  AttrNumber attnum = keyColIdx[i] - 1;
4069 
4070  finfo = &hashfunctions[i];
4071  fcinfo = palloc0(SizeForFunctionCallInfo(1));
4072 
4073  /* Initialize function call parameter structure too */
4074  InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4075 
4076  /*
4077  * Fetch inner Var for this attnum and store it in the 1st arg of the
4078  * hash func.
4079  */
4080  scratch.opcode = EEOP_INNER_VAR;
4081  scratch.resvalue = &fcinfo->args[0].value;
4082  scratch.resnull = &fcinfo->args[0].isnull;
4083  scratch.d.var.attnum = attnum;
4084  scratch.d.var.vartype = TupleDescAttr(desc, attnum)->atttypid;
4085 
4086  ExprEvalPushStep(state, &scratch);
4087 
4088  /* Call the hash function */
4089  scratch.opcode = opcode;
4090 
4091  if (i == numCols - 1)
4092  {
4093  /*
4094  * The result for hashing the final column is stored in the
4095  * ExprState.
4096  */
4097  scratch.resvalue = &state->resvalue;
4098  scratch.resnull = &state->resnull;
4099  }
4100  else
4101  {
4102  Assert(iresult != NULL);
4103 
4104  /* intermediate values are stored in an intermediate result */
4105  scratch.resvalue = &iresult->value;
4106  scratch.resnull = &iresult->isnull;
4107  }
4108 
4109  /*
4110  * NEXT32 opcodes need to look at the intermediate result. We might
4111  * as well just set this for all ops. FIRSTs won't look at it.
4112  */
4113  scratch.d.hashdatum.iresult = iresult;
4114 
4115  scratch.d.hashdatum.finfo = finfo;
4116  scratch.d.hashdatum.fcinfo_data = fcinfo;
4117  scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4118  scratch.d.hashdatum.jumpdone = -1;
4119 
4120  ExprEvalPushStep(state, &scratch);
4121 
4122  /* subsequent attnums must be combined with the previous */
4123  opcode = EEOP_HASHDATUM_NEXT32;
4124  }
4125 
4126  scratch.resvalue = NULL;
4127  scratch.resnull = NULL;
4128  scratch.opcode = EEOP_DONE;
4129  ExprEvalPushStep(state, &scratch);
4130 
4132 
4133  return state;
4134 }
int16 AttrNumber
Definition: attnum.h:21
#define Max(x, y)
Definition: c.h:952
int16 attnum
Definition: pg_attribute.h:74

References FunctionCallInfoBaseData::args, Assert, attnum, ExprEvalStep::d, EEOP_DONE, EEOP_HASHDATUM_FIRST, EEOP_HASHDATUM_NEXT32, EEOP_HASHDATUM_SET_INITVAL, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, ExecComputeSlotInfo(), ExecReadyExpr(), ExprEvalPushStep(), ExprEvalStep::fetch, FmgrInfo::fn_addr, ExprEvalStep::hashdatum, ExprEvalStep::hashdatum_initvalue, i, InitFunctionCallInfoData, NullableDatum::isnull, makeNode, Max, ExprEvalStep::opcode, palloc(), palloc0(), ExprEvalStep::resnull, ExprEvalStep::resvalue, SizeForFunctionCallInfo, TupleDescAttr, UInt32GetDatum(), NullableDatum::value, and ExprEvalStep::var.

Referenced by BuildTupleHashTableExt(), and ExecInitSubPlan().

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

4485 {
4487  ExprEvalStep scratch = {0};
4488  int maxatt = list_length(param_exprs);
4489  List *adjust_jumps = NIL;
4490  ListCell *lc;
4491 
4492  state->expr = NULL;
4493  state->flags = EEO_FLAG_IS_QUAL;
4494  state->parent = parent;
4495 
4496  scratch.resvalue = &state->resvalue;
4497  scratch.resnull = &state->resnull;
4498 
4499  /* push deform steps */
4500  scratch.opcode = EEOP_INNER_FETCHSOME;
4501  scratch.d.fetch.last_var = maxatt;
4502  scratch.d.fetch.fixed = false;
4503  scratch.d.fetch.known_desc = desc;
4504  scratch.d.fetch.kind = lops;
4505  if (ExecComputeSlotInfo(state, &scratch))
4506  ExprEvalPushStep(state, &scratch);
4507 
4508  scratch.opcode = EEOP_OUTER_FETCHSOME;
4509  scratch.d.fetch.last_var = maxatt;
4510  scratch.d.fetch.fixed = false;
4511  scratch.d.fetch.known_desc = desc;
4512  scratch.d.fetch.kind = rops;
4513  if (ExecComputeSlotInfo(state, &scratch))
4514  ExprEvalPushStep(state, &scratch);
4515 
4516  for (int attno = 0; attno < maxatt; attno++)
4517  {
4518  Form_pg_attribute att = TupleDescAttr(desc, attno);
4519  Oid foid = eqfunctions[attno];
4520  Oid collid = collations[attno];
4521  FmgrInfo *finfo;
4522  FunctionCallInfo fcinfo;
4523  AclResult aclresult;
4524 
4525  /* Check permission to call function */
4526  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4527  if (aclresult != ACLCHECK_OK)
4528  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4529 
4531 
4532  /* Set up the primary fmgr lookup information */
4533  finfo = palloc0(sizeof(FmgrInfo));
4534  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4535  fmgr_info(foid, finfo);
4536  fmgr_info_set_expr(NULL, finfo);
4537  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4538  collid, NULL, NULL);
4539 
4540  /* left arg */
4541  scratch.opcode = EEOP_INNER_VAR;
4542  scratch.d.var.attnum = attno;
4543  scratch.d.var.vartype = att->atttypid;
4544  scratch.resvalue = &fcinfo->args[0].value;
4545  scratch.resnull = &fcinfo->args[0].isnull;
4546  ExprEvalPushStep(state, &scratch);
4547 
4548  /* right arg */
4549  scratch.opcode = EEOP_OUTER_VAR;
4550  scratch.d.var.attnum = attno;
4551  scratch.d.var.vartype = att->atttypid;
4552  scratch.resvalue = &fcinfo->args[1].value;
4553  scratch.resnull = &fcinfo->args[1].isnull;
4554  ExprEvalPushStep(state, &scratch);
4555 
4556  /* evaluate distinctness */
4557  scratch.opcode = EEOP_NOT_DISTINCT;
4558  scratch.d.func.finfo = finfo;
4559  scratch.d.func.fcinfo_data = fcinfo;
4560  scratch.d.func.fn_addr = finfo->fn_addr;
4561  scratch.d.func.nargs = 2;
4562  scratch.resvalue = &state->resvalue;
4563  scratch.resnull = &state->resnull;
4564  ExprEvalPushStep(state, &scratch);
4565 
4566  /* then emit EEOP_QUAL to detect if result is false (or null) */
4567  scratch.opcode = EEOP_QUAL;
4568  scratch.d.qualexpr.jumpdone = -1;
4569  scratch.resvalue = &state->resvalue;
4570  scratch.resnull = &state->resnull;
4571  ExprEvalPushStep(state, &scratch);
4572  adjust_jumps = lappend_int(adjust_jumps,
4573  state->steps_len - 1);
4574  }
4575 
4576  /* adjust jump targets */
4577  foreach(lc, adjust_jumps)
4578  {
4579  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4580 
4581  Assert(as->opcode == EEOP_QUAL);
4582  Assert(as->d.qualexpr.jumpdone == -1);
4583  as->d.qualexpr.jumpdone = state->steps_len;
4584  }
4585 
4586  scratch.resvalue = NULL;
4587  scratch.resnull = NULL;
4588  scratch.opcode = EEOP_DONE;
4589  ExprEvalPushStep(state, &scratch);
4590 
4592 
4593  return state;
4594 }

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

Referenced by ExecInitMemoize().

◆ ExecBuildProjectionInfo()

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

Definition at line 365 of file execExpr.c.

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

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

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

◆ ExecBuildSlotValueDescription()

char* ExecBuildSlotValueDescription ( Oid  reloid,
TupleTableSlot slot,
TupleDesc  tupdesc,
Bitmapset modifiedCols,
int  maxfieldlen 
)

Definition at line 2223 of file execMain.c.

2228 {
2230  StringInfoData collist;
2231  bool write_comma = false;
2232  bool write_comma_collist = false;
2233  int i;
2234  AclResult aclresult;
2235  bool table_perm = false;
2236  bool any_perm = false;
2237 
2238  /*
2239  * Check if RLS is enabled and should be active for the relation; if so,
2240  * then don't return anything. Otherwise, go through normal permission
2241  * checks.
2242  */
2243  if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2244  return NULL;
2245 
2246  initStringInfo(&buf);
2247 
2248  appendStringInfoChar(&buf, '(');
2249 
2250  /*
2251  * Check if the user has permissions to see the row. Table-level SELECT
2252  * allows access to all columns. If the user does not have table-level
2253  * SELECT then we check each column and include those the user has SELECT
2254  * rights on. Additionally, we always include columns the user provided
2255  * data for.
2256  */
2257  aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2258  if (aclresult != ACLCHECK_OK)
2259  {
2260  /* Set up the buffer for the column list */
2261  initStringInfo(&collist);
2262  appendStringInfoChar(&collist, '(');
2263  }
2264  else
2265  table_perm = any_perm = true;
2266 
2267  /* Make sure the tuple is fully deconstructed */
2268  slot_getallattrs(slot);
2269 
2270  for (i = 0; i < tupdesc->natts; i++)
2271  {
2272  bool column_perm = false;
2273  char *val;
2274  int vallen;
2275  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2276 
2277  /* ignore dropped columns */
2278  if (att->attisdropped)
2279  continue;
2280 
2281  if (!table_perm)
2282  {
2283  /*
2284  * No table-level SELECT, so need to make sure they either have
2285  * SELECT rights on the column or that they have provided the data
2286  * for the column. If not, omit this column from the error
2287  * message.
2288  */
2289  aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2290  GetUserId(), ACL_SELECT);
2292  modifiedCols) || aclresult == ACLCHECK_OK)
2293  {
2294  column_perm = any_perm = true;
2295 
2296  if (write_comma_collist)
2297  appendStringInfoString(&collist, ", ");
2298  else
2299  write_comma_collist = true;
2300 
2301  appendStringInfoString(&collist, NameStr(att->attname));
2302  }
2303  }
2304 
2305  if (table_perm || column_perm)
2306  {
2307  if (slot->tts_isnull[i])
2308  val = "null";
2309  else
2310  {
2311  Oid foutoid;
2312  bool typisvarlena;
2313 
2314  getTypeOutputInfo(att->atttypid,
2315  &foutoid, &typisvarlena);
2316  val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2317  }
2318 
2319  if (write_comma)
2320  appendStringInfoString(&buf, ", ");
2321  else
2322  write_comma = true;
2323 
2324  /* truncate if needed */
2325  vallen = strlen(val);
2326  if (vallen <= maxfieldlen)
2327  appendBinaryStringInfo(&buf, val, vallen);
2328  else
2329  {
2330  vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2331  appendBinaryStringInfo(&buf, val, vallen);
2332  appendStringInfoString(&buf, "...");
2333  }
2334  }
2335  }
2336 
2337  /* If we end up with zero columns being returned, then return NULL. */
2338  if (!any_perm)
2339  return NULL;
2340 
2341  appendStringInfoChar(&buf, ')');
2342 
2343  if (!table_perm)
2344  {
2345  appendStringInfoString(&collist, ") = ");
2346  appendBinaryStringInfo(&collist, buf.data, buf.len);
2347 
2348  return collist.data;
2349  }
2350 
2351  return buf.data;
2352 }
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:3842
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4013
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
#define NameStr(name)
Definition: c.h:700
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
long val
Definition: informix.c:689
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1083
#define ACL_SELECT
Definition: parsenodes.h:77
static char * buf
Definition: pg_test_fsync.c:72
#define InvalidOid
Definition: postgres_ext.h:36
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
@ RLS_ENABLED
Definition: rls.h:45
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:230
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:191
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:368

References ACL_SELECT, ACLCHECK_OK, appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), bms_is_member(), buf, check_enable_rls(), StringInfoData::data, FirstLowInvalidHeapAttributeNumber, getTypeOutputInfo(), GetUserId(), i, initStringInfo(), InvalidOid, NameStr, TupleDescData::natts, OidOutputFunctionCall(), pg_attribute_aclcheck(), pg_class_aclcheck(), pg_mbcliplen(), RLS_ENABLED, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TupleDescAttr, and val.

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

◆ ExecBuildUpdateProjection()

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

Definition at line 525 of file execExpr.c.

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

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

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

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)

Definition at line 850 of file execExpr.c.

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

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

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

◆ ExecCheckIndexConstraints()

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

Definition at line 536 of file execIndexing.c.

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

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(), and FindConflictTuple().

◆ ExecCheckPermissions()

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

Definition at line 579 of file execMain.c.

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

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

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

◆ ExecCleanTargetListLength()

int ExecCleanTargetListLength ( List targetlist)

Definition at line 1121 of file execUtils.c.

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

References len, and lfirst_node.

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

◆ ExecCleanTypeFromTL()

TupleDesc ExecCleanTypeFromTL ( List targetList)

Definition at line 2037 of file execTuples.c.

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

References ExecTypeFromTLInternal().

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

◆ ExecCloseIndices()

void ExecCloseIndices ( ResultRelInfo resultRelInfo)

Definition at line 236 of file execIndexing.c.

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

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

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

◆ ExecCloseRangeTableRelations()

void ExecCloseRangeTableRelations ( EState estate)

Definition at line 1583 of file execMain.c.

1584 {
1585  int i;
1586 
1587  for (i = 0; i < estate->es_range_table_size; i++)
1588  {
1589  if (estate->es_relations[i])
1590  table_close(estate->es_relations[i], NoLock);
1591  }
1592 }
#define NoLock
Definition: lockdefs.h:34
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126

References EState::es_range_table_size, EState::es_relations, i, NoLock, and table_close().

Referenced by CopyFrom(), and ExecEndPlan().

◆ ExecCloseResultRelations()

void ExecCloseResultRelations ( EState estate)

Definition at line 1523 of file execMain.c.

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

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

562 {
563  if (tlist_matches_tupdesc(planstate,
564  planstate->plan->targetlist,
565  varno,
566  inputDesc))
567  {
568  planstate->ps_ProjInfo = NULL;
569  planstate->resultopsset = planstate->scanopsset;
570  planstate->resultopsfixed = planstate->scanopsfixed;
571  planstate->resultops = planstate->scanops;
572  }
573  else
574  {
575  if (!planstate->ps_ResultTupleSlot)
576  {
577  ExecInitResultSlot(planstate, &TTSOpsVirtual);
578  planstate->resultops = &TTSOpsVirtual;
579  planstate->resultopsfixed = true;
580  planstate->resultopsset = true;
581  }
582  ExecAssignProjectionInfo(planstate, inputDesc);
583  }
584 }
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1866
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
Definition: execUtils.c:587
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:540
const TupleTableSlotOps * resultops
Definition: execnodes.h:1203
bool resultopsset
Definition: execnodes.h:1211
const TupleTableSlotOps * scanops
Definition: execnodes.h:1200
bool scanopsset
Definition: execnodes.h:1208
bool scanopsfixed
Definition: execnodes.h:1204
bool resultopsfixed
Definition: execnodes.h:1207

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

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

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

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

◆ ExecCreateScanSlotFromOuterPlan()

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

Definition at line 661 of file execUtils.c.

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

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

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

◆ execCurrentOf()

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

Definition at line 44 of file execCurrent.c.

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

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

Referenced by TidListEval().

◆ ExecEndNode()

void ExecEndNode ( PlanState node)

Definition at line 562 of file execProcnode.c.

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

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

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

◆ ExecEvalExpr()

◆ ExecEvalExprSwitchContext()

◆ ExecFilterJunk()

TupleTableSlot* ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 247 of file execJunk.c.

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

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

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  {