Files
openGauss-server/src/include/executor/executor.h
dengxuyue 1567043064 同步source code
日期: 12-26
    revision: ee5b054c
2020-12-28 22:19:21 +08:00

482 lines
22 KiB
C++
Executable File

/* -------------------------------------------------------------------------
*
* executor.h
* support for the POSTGRES executor module
*
*
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/executor/executor.h
*
* -------------------------------------------------------------------------
*/
#ifndef EXECUTOR_H
#define EXECUTOR_H
#include "executor/execdesc.h"
#include "nodes/parsenodes.h"
#include "nodes/params.h"
#include "pgxc/pgxc.h"
#include "utils/memprot.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
#include "utils/partitionmap_gs.h"
#include "utils/plpgsql.h"
/*
* The "eflags" argument to ExecutorStart and the various ExecInitNode
* routines is a bitwise OR of the following flag bits, which tell the
* called plan node what to expect. Note that the flags will get modified
* as they are passed down the plan tree, since an upper node may require
* functionality in its subnode not demanded of the plan as a whole
* (example: MergeJoin requires mark/restore capability in its inner input),
* or an upper node may shield its input from some functionality requirement
* (example: Materialize shields its input from needing to do backward scan).
*
* EXPLAIN_ONLY indicates that the plan tree is being initialized just so
* EXPLAIN can print it out; it will not be run. Hence, no side-effects
* of startup should occur. However, error checks (such as permission checks)
* should be performed.
*
* REWIND indicates that the plan node should try to efficiently support
* rescans without parameter changes. (Nodes must support ExecReScan calls
* in any case, but if this flag was not given, they are at liberty to do it
* through complete recalculation. Note that a parameter change forces a
* full recalculation in any case.)
*
* BACKWARD indicates that the plan node must respect the es_direction flag.
* When this is not passed, the plan node will only be run forwards.
*
* MARK indicates that the plan node must support Mark/Restore calls.
* When this is not passed, no Mark/Restore will occur.
*
* SKIP_TRIGGERS tells ExecutorStart/ExecutorFinish to skip calling
* AfterTriggerBeginQuery/AfterTriggerEndQuery. This does not necessarily
* mean that the plan can't queue any AFTER triggers; just that the caller
* is responsible for there being a trigger context for them to be queued in.
*
* WITH/WITHOUT_OIDS tell the executor to emit tuples with or without space
* for OIDs, respectively. These are currently used only for CREATE TABLE AS.
* If neither is set, the plan may or may not produce tuples including OIDs.
*/
#define EXEC_FLAG_EXPLAIN_ONLY 0x0001 /* EXPLAIN, no ANALYZE */
#define EXEC_FLAG_REWIND 0x0002 /* need efficient rescan */
#define EXEC_FLAG_BACKWARD 0x0004 /* need backward scan */
#define EXEC_FLAG_MARK 0x0008 /* need mark/restore */
#define EXEC_FLAG_SKIP_TRIGGERS 0x0010 /* skip AfterTrigger calls */
#define EXEC_FLAG_WITH_OIDS 0x0020 /* force OIDs in returned tuples */
#define EXEC_FLAG_WITHOUT_OIDS 0x0040 /* force no OIDs in returned tuples */
#define EXEC_FLAG_WITH_NO_DATA 0x0080 /* rel scannability doesn't matter */
extern inline bool is_errmodule_enable(int elevel, ModuleId mod_id);
#define STREAM_LOG(level, format, ...) \
do { \
if (is_errmodule_enable(level, MOD_STREAM)) { \
ereport(level, (errmodule(MOD_STREAM), errmsg(format, ##__VA_ARGS__), ignore_interrupt(true))); \
} \
} while (0)
#define MEMCTL_LOG(level, format, ...) \
do { \
if (is_errmodule_enable(level, MOD_MEM)) { \
ereport(level, (errmodule(MOD_MEM), errmsg(format, ##__VA_ARGS__), ignore_interrupt(true))); \
} \
} while (0)
#ifdef USE_ASSERT_CHECKING
#define EARLY_FREE_LOG(A)
#else
#define EARLY_FREE_LOG(A)
#endif
#ifdef USE_ASSERT_CHECKING
#define RECURSIVE_LOG(level, format, ...) \
do { \
ereport(level, (errmsg(format, ##__VA_ARGS__))); \
} while (0)
#else
#define RECURSIVE_LOG(level, format, ...) \
do { \
ereport(DEBUG1, (errmsg(format, ##__VA_ARGS__))); \
} while (0)
#endif
#define SET_DOP(dop) (dop > 1 ? dop : 1)
/*
* Calculate the memory restriction in each thread.
* And the memeory in each thread must be larger than 64K.
*/
#define SET_NODEMEM(opmem, dop) \
((opmem > 0 ? opmem : u_sess->attr.attr_memory.work_mem) / \
((opmem > 0 ? opmem : u_sess->attr.attr_memory.work_mem) > (SET_DOP(dop) * 64) ? SET_DOP(dop) : 1))
#define SET_NUMGROUPS(node) \
(node->numGroups / SET_DOP(node->plan.dop) > 0 ? node->numGroups / SET_DOP(node->plan.dop) : 1)
#define HAS_INSTR(node, dnonly) \
(!dnonly || IS_PGXC_DATANODE) && u_sess->instr_cxt.global_instr != NULL && (node)->ps.instrument != NULL
/*
* ExecEvalExpr was formerly a function containing a switch statement;
* now it's just a macro invoking the function pointed to by an ExprState
* node. Beware of double evaluation of the ExprState argument!
*/
#define ExecEvalExpr(expr, econtext, isNull, isDone) ((*(expr)->evalfunc)(expr, econtext, isNull, isDone))
/*
* recursive union macro
*/
#define INVALID_RU_PLANNODE_ID 0
#define EXEC_IN_RECURSIVE_MODE(x) (((Plan*)x)->recursive_union_plan_nodeid != INVALID_RU_PLANNODE_ID)
/* Hook for plugins to get control in ExecutorStart() */
typedef void (*ExecutorStart_hook_type)(QueryDesc* queryDesc, int eflags);
extern THR_LOCAL PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook;
/* Hook for plugins to get control in ExecutorRun() */
typedef void (*ExecutorRun_hook_type)(QueryDesc* queryDesc, ScanDirection direction, long count);
extern THR_LOCAL PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook;
/* Hook for plugins to get control in ExecutorFinish() */
typedef void (*ExecutorFinish_hook_type)(QueryDesc* queryDesc);
extern THR_LOCAL PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook;
/* Hook for plugins to get control in ExecutorEnd() */
typedef void (*ExecutorEnd_hook_type)(QueryDesc* queryDesc);
extern THR_LOCAL PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook;
/* Hook for plugins to get control in ExecCheckRTPerms() */
typedef bool (*ExecutorCheckPerms_hook_type)(List*, bool);
extern THR_LOCAL PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook;
/*
* prototypes from functions in execAmi.c
*/
extern void ExecReScan(PlanState* node);
extern void ExecMarkPos(PlanState* node);
extern void ExecRestrPos(PlanState* node);
extern bool ExecSupportsMarkRestore(NodeTag plantype);
extern bool ExecSupportsBackwardScan(Plan* node);
extern bool ExecMaterializesOutput(NodeTag plantype);
/*
* prototypes from functions in execCurrent.c
*/
extern bool execCurrentOf(CurrentOfExpr* cexpr, ExprContext* econtext, Relation relation, ItemPointer current_tid,
RelationPtr partitionOfCursor_tid);
#ifdef PGXC
ScanState* search_plan_tree(PlanState* node, Oid table_oid);
#endif
/*
* prototypes from functions in execGrouping.c
*/
extern bool execTuplesMatch(TupleTableSlot* slot1, TupleTableSlot* slot2, int numCols, AttrNumber* matchColIdx,
FmgrInfo* eqfunctions, MemoryContext evalContext);
extern bool execTuplesUnequal(TupleTableSlot* slot1, TupleTableSlot* slot2, int numCols, AttrNumber* matchColIdx,
FmgrInfo* eqfunctions, MemoryContext evalContext);
extern FmgrInfo* execTuplesMatchPrepare(int numCols, Oid* eqOperators);
extern void execTuplesHashPrepare(int numCols, Oid* eqOperators, FmgrInfo** eqFunctions, FmgrInfo** hashFunctions);
extern TupleHashTable BuildTupleHashTable(int numCols, AttrNumber* keyColIdx, FmgrInfo* eqfunctions,
FmgrInfo* hashfunctions, long nbuckets, Size entrysize, MemoryContext tablecxt, MemoryContext tempcxt, int workMem);
extern TupleHashEntry LookupTupleHashEntry(
TupleHashTable hashtable, TupleTableSlot* slot, bool* isnew, bool isinserthashtbl = true);
extern TupleHashEntry FindTupleHashEntry(
TupleHashTable hashtable, TupleTableSlot* slot, FmgrInfo* eqfunctions, FmgrInfo* hashfunctions);
/*
* prototypes from functions in execJunk.c
*/
extern JunkFilter* ExecInitJunkFilter(List* targetList, bool hasoid, TupleTableSlot* slot, TableAmType tam = TAM_HEAP);
extern JunkFilter* ExecInitJunkFilterConversion(List* targetList, TupleDesc cleanTupType, TupleTableSlot* slot);
extern AttrNumber ExecFindJunkAttribute(JunkFilter* junkfilter, const char* attrName);
extern AttrNumber ExecFindJunkAttributeInTlist(List* targetlist, const char* attrName);
extern Datum ExecGetJunkAttribute(TupleTableSlot* slot, AttrNumber attno, bool* isNull);
extern TupleTableSlot* ExecFilterJunk(JunkFilter* junkfilter, TupleTableSlot* slot);
extern void ExecSetjunkFilteDescriptor(JunkFilter* junkfilter, TupleDesc tupdesc);
#ifdef PGXC
extern List* ExecFindJunkPrimaryKeys(List* targetlist);
#endif
extern VectorBatch* BatchExecFilterJunk(JunkFilter* junkfilter, VectorBatch* batch);
extern void BatchCheckNodeIdentifier(JunkFilter* junkfilter, VectorBatch* batch);
extern int ExecGetPlanNodeid(void);
/*
* prototypes from functions in execMain.c
*/
extern void ExecutorStart(QueryDesc* queryDesc, int eflags);
extern void standard_ExecutorStart(QueryDesc* queryDesc, int eflags);
extern void ExecutorRun(QueryDesc* queryDesc, ScanDirection direction, long count);
extern void standard_ExecutorRun(QueryDesc* queryDesc, ScanDirection direction, long count);
extern void ExecutorFinish(QueryDesc* queryDesc);
extern void standard_ExecutorFinish(QueryDesc* queryDesc);
extern void ExecutorEnd(QueryDesc* queryDesc);
extern void standard_ExecutorEnd(QueryDesc* queryDesc);
extern void ExecutorRewind(QueryDesc* queryDesc);
extern bool ExecCheckRTPerms(List* rangeTable, bool ereport_on_violation);
extern void CheckValidResultRel(Relation resultRel, CmdType operation);
extern void InitResultRelInfo(
ResultRelInfo* resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, int instrument_options);
extern ResultRelInfo* ExecGetTriggerResultRel(EState* estate, Oid relid);
extern bool ExecContextForcesOids(PlanState* planstate, bool* hasoids);
extern void ExecConstraints(ResultRelInfo* resultRelInfo, TupleTableSlot* slot, EState* estate);
extern ExecRowMark* ExecFindRowMark(EState* estate, Index rti);
extern ExecAuxRowMark* ExecBuildAuxRowMark(ExecRowMark* erm, List* targetlist);
extern TupleTableSlot* EvalPlanQual(
EState* estate, EPQState* epqstate, Relation relation, Index rti, ItemPointer tid, TransactionId priorXmax);
extern HeapTuple heap_lock_updated(
CommandId cid, Relation relation, int lockmode, ItemPointer tid, TransactionId priorXmax);
extern void EvalPlanQualInit(EPQState* epqstate, EState* estate, Plan* subplan, List* auxrowmarks, int epqParam);
extern void EvalPlanQualSetPlan(EPQState* epqstate, Plan* subplan, List* auxrowmarks);
extern void EvalPlanQualSetTuple(EPQState* epqstate, Index rti, HeapTuple tuple);
extern HeapTuple EvalPlanQualGetTuple(EPQState* epqstate, Index rti);
#define EvalPlanQualSetSlot(epqstate, slot) ((epqstate)->origslot = (slot))
extern void EvalPlanQualFetchRowMarks(EPQState* epqstate);
extern TupleTableSlot* EvalPlanQualNext(EPQState* epqstate);
extern void EvalPlanQualBegin(EPQState* epqstate, EState* parentestate);
extern void EvalPlanQualEnd(EPQState* epqstate);
/*
* prototypes from functions in execProcnode.c
*/
extern PlanState* ExecInitNode(Plan* node, EState* estate, int eflags);
extern TupleTableSlot* ExecProcNode(PlanState* node);
extern Node* MultiExecProcNode(PlanState* node);
extern void ExecEndNode(PlanState* node);
extern bool NeedStubExecution(Plan* plan);
extern long ExecGetPlanMemCost(Plan* node);
/*
* prototypes from functions in execQual.c
*/
extern Datum GetAttributeByNum(HeapTupleHeader tuple, AttrNumber attrno, bool* isNull);
extern Datum GetAttributeByName(HeapTupleHeader tuple, const char* attname, bool* isNull);
extern Tuplestorestate* ExecMakeTableFunctionResult(
ExprState* funcexpr, ExprContext* econtext, TupleDesc expectedDesc, bool randomAccess, FunctionScanState* node);
extern Datum ExecEvalExprSwitchContext(
ExprState* expression, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone);
extern ExprState* ExecInitExpr(Expr* node, PlanState* parent);
extern ExprState* ExecPrepareExpr(Expr* node, EState* estate);
extern bool ExecQual(List* qual, ExprContext* econtext, bool resultForNull);
extern int ExecTargetListLength(List* targetlist);
extern int ExecCleanTargetListLength(List* targetlist);
extern TupleTableSlot* ExecProject(ProjectionInfo* projInfo, ExprDoneCond* isDone);
extern TupleTableSlot* ExecScan(ScanState* node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd);
extern void ExecAssignScanProjectionInfo(ScanState* node);
extern void ExecScanReScan(ScanState* node);
/*
* prototypes from functions in execTuples.c
*/
extern void ExecInitResultTupleSlot(EState* estate, PlanState* planstate, TableAmType tam = TAM_HEAP);
extern void ExecInitScanTupleSlot(EState* estate, ScanState* scanstate, TableAmType tam = TAM_HEAP);
extern TupleTableSlot* ExecInitExtraTupleSlot(EState* estate, TableAmType tam = TAM_HEAP);
extern TupleTableSlot* ExecInitNullTupleSlot(EState* estate, TupleDesc tupType);
extern TupleDesc ExecTypeFromTL(List* targetList, bool hasoid, bool markdropped = false, TableAmType tam = TAM_HEAP);
extern TupleDesc ExecCleanTypeFromTL(List* targetList, bool hasoid, TableAmType tam = TAM_HEAP);
extern TupleDesc ExecTypeFromExprList(List* exprList, List* namesList, TableAmType tam = TAM_HEAP);
extern void UpdateChangedParamSet(PlanState* node, Bitmapset* newchg);
typedef struct TupOutputState {
TupleTableSlot* slot;
DestReceiver* dest;
} TupOutputState;
extern TupOutputState* begin_tup_output_tupdesc(DestReceiver* dest, TupleDesc tupdesc);
extern void do_tup_output(
TupOutputState* tstate, Datum* values, size_t values_len, const bool* isnull, size_t isnull_len);
extern int do_text_output_multiline(TupOutputState* tstate, char* text);
extern void end_tup_output(TupOutputState* tstate);
/*
* Write a single line of text given as a C string.
*
* Should only be used with a single-TEXT-attribute tupdesc.
*/
#define do_text_output_oneline(tstate, str_to_emit) \
do { \
Datum values_[1]; \
bool isnull_[1]; \
values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
isnull_[0] = false; \
do_tup_output(tstate, values_, 1, isnull_, 1); \
pfree(DatumGetPointer(values_[0])); \
} while (0)
/*
* prototypes from functions in execUtils.c
*/
extern EState* CreateExecutorState(void);
extern void FreeExecutorState(EState* estate);
extern ExprContext* CreateExprContext(EState* estate);
extern ExprContext* CreateStandaloneExprContext(void);
extern void FreeExprContext(ExprContext* econtext, bool isCommit);
extern void ReScanExprContext(ExprContext* econtext);
#define ResetExprContext(econtext) MemoryContextReset((econtext)->ecxt_per_tuple_memory)
extern ExprContext* MakePerTupleExprContext(EState* estate);
#define RuntimeBinding(func, strategy) (this->*func[strategy])
#define InvokeFp(func) (this->*func)
/* Get an EState's per-output-tuple exprcontext, making it if first use */
#define GetPerTupleExprContext(estate) \
((estate)->es_per_tuple_exprcontext ? (estate)->es_per_tuple_exprcontext : MakePerTupleExprContext(estate))
#define GetPerTupleMemoryContext(estate) (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
/* Reset an EState's per-output-tuple exprcontext, if one's been created */
#define ResetPerTupleExprContext(estate) \
do { \
if ((estate)->es_per_tuple_exprcontext) \
ResetExprContext((estate)->es_per_tuple_exprcontext); \
} while (0)
/* Reset an Slot's per-output-tuple context, if one's been created */
#define ResetSlotPerTupleContext(slot) \
do { \
if ((slot) && (slot)->tts_per_tuple_mcxt) \
MemoryContextReset((slot)->tts_per_tuple_mcxt); \
} while (0)
extern void ExecAssignExprContext(EState* estate, PlanState* planstate);
extern void ExecAssignResultType(PlanState* planstate, TupleDesc tupDesc);
extern void ExecAssignResultTypeFromTL(PlanState* planstate, TableAmType tam = TAM_HEAP);
extern TupleDesc ExecGetResultType(PlanState* planstate);
extern void ExecAssignVectorForExprEval(ExprContext* econtext);
extern ProjectionInfo* ExecBuildProjectionInfo(
List* targetList, ExprContext* econtext, TupleTableSlot* slot, TupleDesc inputDesc);
extern void ExecAssignProjectionInfo(PlanState* planstate, TupleDesc inputDesc);
extern void ExecAssignScanProjectionInfoWithVarno(ScanState* node, Index varno);
extern void ExecFreeExprContext(PlanState* planstate);
extern TupleDesc ExecGetScanType(ScanState* scanstate);
extern void ExecAssignScanType(ScanState* scanstate, TupleDesc tupDesc);
extern void ExecAssignScanTypeFromOuterPlan(ScanState* scanstate);
extern bool ExecRelationIsTargetRelation(EState* estate, Index scanrelid);
extern Relation ExecOpenScanRelation(EState* estate, Index scanrelid);
extern void ExecCloseScanRelation(Relation scanrel);
extern Partition ExecOpenScanParitition(
EState* estate, Relation parent, PartitionIdentifier* partID, LOCKMODE lockmode);
extern void ExecOpenIndices(ResultRelInfo* resultRelInfo, bool speculative);
extern void ExecCloseIndices(ResultRelInfo* resultRelInfo);
extern List* ExecInsertIndexTuples(
TupleTableSlot* slot, ItemPointer tupleid, EState* estate, Relation targetPartRel, Partition p, int2 bucketId, bool* conflict);
extern bool ExecCheckIndexConstraints(TupleTableSlot* slot, EState* estate,
Relation targetRel, Partition p, int2 bucketId, ItemPointer conflictTid);
extern bool check_exclusion_constraint(Relation heap, Relation index, IndexInfo* indexInfo, ItemPointer tupleid,
Datum* values, const bool* isnull, EState* estate, bool newIndex, bool errorOK);
extern void RegisterExprContextCallback(ExprContext* econtext, ExprContextCallbackFunction function, Datum arg);
extern void UnregisterExprContextCallback(ExprContext* econtext, ExprContextCallbackFunction function, Datum arg);
extern List* GetAccessedVarnoList(List* targetList, List* qual);
extern ProjectionInfo* ExecBuildVecProjectionInfo(
List* targetList, List* nt_qual, ExprContext* econtext, TupleTableSlot* slot, TupleDesc inputDesc);
extern bool tlist_matches_tupdesc(PlanState* ps, List* tlist, Index varno, TupleDesc tupdesc);
extern int PthreadMutexLock(ResourceOwner owner, pthread_mutex_t* mutex, bool trace = true);
extern int PthreadMutexTryLock(ResourceOwner owner, pthread_mutex_t* mutex, bool trace = true);
extern int PthreadMutexUnlock(ResourceOwner owner, pthread_mutex_t* mutex, bool trace = true);
extern bool executorEarlyStop();
extern void ExecEarlyFree(PlanState* node);
extern void ExecEarlyFreeBody(PlanState* node);
extern void ExecReSetRecursivePlanTree(PlanState* node);
extern void ExplainNodePending(PlanState* result_plan);
extern void ExplainNodeFinish(PlanState* result_plan, PlannedStmt* pstmt, TimestampTz current_time, bool is_pending);
extern void ExecCopyDataFromDatum(PLpgSQL_datum** datums, int dno, Cursor_Data* target_cursor);
extern void ExecCopyDataToDatum(PLpgSQL_datum** datums, int dno, Cursor_Data* target_cursor);
// AutoMutexLock
// Auto object for non-recursive pthread_mutex_t lock
//
class AutoMutexLock {
public:
AutoMutexLock(pthread_mutex_t* mutex, bool trace = true)
: m_mutex(mutex), m_fLocked(false), m_trace(trace), m_owner(t_thrd.utils_cxt.CurrentResourceOwner)
{}
~AutoMutexLock()
{
unLock();
}
inline void lock()
{
// Guard against recursive lock
//
if (!m_fLocked) {
int ret = 0;
ret = PthreadMutexLock(m_owner, m_mutex, m_trace);
m_fLocked = (ret == 0 ? true : false);
if (!m_fLocked) {
/* this should never happen, system may be completely in a mess */
if (ErrorContext == NULL) {
write_stderr(_("ERROR: pthread mutex lock failed, query id %lu: %s\n"),
u_sess->debug_query_id,
strerror(ret));
abort();
} else
ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), errmsg("pthread mutex lock failed: %s", strerror(ret))));
}
}
}
inline bool TryLock()
{
// Guard against recursive lock
//
if (!m_fLocked) {
m_fLocked = (PthreadMutexTryLock(m_owner, m_mutex, m_trace) == 0 ? true : false);
return m_fLocked;
}
return false;
}
inline void unLock()
{
if (m_fLocked) {
int ret = 0;
if (t_thrd.utils_cxt.CurrentResourceOwner == NULL)
m_owner = NULL;
ret = PthreadMutexUnlock(m_owner, m_mutex, m_trace);
m_fLocked = (ret == 0 ? false : true);
if (m_fLocked) {
/* this should never happen, system may be completely in a mess */
if (ErrorContext == NULL) {
write_stderr(_("ERROR: pthread mutex unlock failed, query id %lu: %s\n"),
u_sess->debug_query_id,
strerror(ret));
abort();
} else
ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), errmsg("pthread mutex unlock failed: %s", strerror(ret))));
}
}
}
private:
pthread_mutex_t* m_mutex;
bool m_fLocked;
bool m_trace;
ResourceOwner m_owner;
};
#endif /* EXECUTOR_H */