【实现内容】: 修复I9HBFS所示的有脏数据导致unseable索引reindex失败的问题 【根因分析】: 因为openguass insert的时候会忽略掉unusable 索引,导致可以insert重复的数据,导致索引rebuild失败 【实现方案】: 参考pg的实现,insert数据的时候,把unseable索引也更新 【关联需求或issue】: https://gitee.com/opengauss/openGauss-server/issues/I9HBFS
2937 lines
111 KiB
C++
Executable File
2937 lines
111 KiB
C++
Executable File
/* -------------------------------------------------------------------------
|
|
*
|
|
* execnodes.h
|
|
* definitions for executor state nodes
|
|
*
|
|
*
|
|
* Portions Copyright (c) 2021, openGauss Contributors
|
|
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/nodes/execnodes.h
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
#ifndef EXECNODES_H
|
|
#define EXECNODES_H
|
|
|
|
#include "access/genam.h"
|
|
#include "access/relscan.h"
|
|
#include "bulkload/dist_fdw.h"
|
|
#include "executor/instrument.h"
|
|
#include "nodes/params.h"
|
|
#include "nodes/plannodes.h"
|
|
#include "storage/pagecompress.h"
|
|
#include "utils/array.h"
|
|
#include "utils/bloom_filter.h"
|
|
#include "utils/reltrigger.h"
|
|
#include "utils/sortsupport.h"
|
|
#include "utils/tuplesort.h"
|
|
#include "utils/tuplestore.h"
|
|
#include "vecexecutor/vectorbatch.h"
|
|
|
|
#include "db4ai/matrix.h"
|
|
|
|
#ifdef ENABLE_MOT
|
|
// forward declaration for MOT JitContext
|
|
namespace JitExec
|
|
{
|
|
struct MotJitContext;
|
|
}
|
|
#endif
|
|
|
|
#define ATTACH_RIGHT_REF_STATE(planstate) if ((planstate) && (planstate)->ps_ExprContext && (planstate)->plan) {\
|
|
(planstate)->ps_ExprContext->rightRefState = (planstate)->plan->rightRefState; \
|
|
}
|
|
|
|
/* struct for utility statement mem usage */
|
|
typedef struct UtilityDesc {
|
|
double cost; /* cost of utility statement */
|
|
int query_mem[2]; /* max and min mem of utility statement */
|
|
int min_mem; /* operator min mem from cost estimation */
|
|
int assigned_mem; /* statement mem assigned by workload manager */
|
|
} UtilityDesc;
|
|
|
|
/* ----------------
|
|
* IndexInfo information
|
|
*
|
|
* this struct holds the information needed to construct new index
|
|
* entries for a particular index. Used for both index_build and
|
|
* retail creation of index entries.
|
|
*
|
|
* NumIndexAttrs total number of columns in this index
|
|
* NumIndexKeyAttrs number of key columns in index
|
|
* KeyAttrNumbers underlying-rel attribute numbers used as keys
|
|
* (zeroes indicate expressions). It also contains
|
|
* info about included columns.
|
|
* Expressions expr trees for expression entries, or NIL if none
|
|
* ExpressionsState exec state for expressions, or NIL if none
|
|
* Predicate partial-index predicate, or NIL if none
|
|
* PredicateState exec state for predicate, or NIL if none
|
|
* ExclusionOps Per-column exclusion operators, or NULL if none
|
|
* ExclusionProcs Underlying function OIDs for ExclusionOps
|
|
* ExclusionStrats Opclass strategy numbers for ExclusionOps
|
|
* UniqueOps Theses are like Exclusion*, but for unique indexes
|
|
* UniqueProcs
|
|
* UniqueStrats
|
|
* Unique is it a unique index?
|
|
* ReadyForInserts is it valid for inserts?
|
|
* Concurrent are we doing a concurrent index build?
|
|
* BrokenHotChain did we detect any broken HOT chains?
|
|
*
|
|
* ii_Concurrent and ii_BrokenHotChain are used only during index build;
|
|
* they're conventionally set to false otherwise.
|
|
* ----------------
|
|
*/
|
|
typedef struct IndexInfo {
|
|
NodeTag type;
|
|
int ii_NumIndexAttrs; /* total number of columns in index */
|
|
int ii_NumIndexKeyAttrs; /* number of key columns in index */
|
|
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS];
|
|
List* ii_Expressions; /* list of Expr */
|
|
List* ii_ExpressionsState; /* list of ExprState */
|
|
List* ii_Predicate; /* list of Expr */
|
|
List* ii_PredicateState; /* list of ExprState */
|
|
Oid* ii_ExclusionOps; /* array with one entry per column */
|
|
Oid* ii_ExclusionProcs; /* array with one entry per column */
|
|
uint16* ii_ExclusionStrats; /* array with one entry per column */
|
|
Oid *ii_UniqueOps; /* array with one entry per column */
|
|
Oid *ii_UniqueProcs; /* array with one entry per column */
|
|
uint16 *ii_UniqueStrats; /* array with one entry per column */
|
|
bool ii_Unique;
|
|
bool ii_ReadyForInserts;
|
|
bool ii_Concurrent;
|
|
bool ii_BrokenHotChain;
|
|
int ii_ParallelWorkers;
|
|
short ii_PgClassAttrId;
|
|
UtilityDesc ii_desc; /* meminfo for index create */
|
|
} IndexInfo;
|
|
|
|
/* ----------------
|
|
* ExprContext_CB
|
|
*
|
|
* List of callbacks to be called at ExprContext shutdown.
|
|
* ----------------
|
|
*/
|
|
typedef void (*ExprContextCallbackFunction)(Datum arg);
|
|
|
|
typedef struct ExprContext_CB {
|
|
struct ExprContext_CB* next;
|
|
ExprContextCallbackFunction function;
|
|
ResourceOwner resowner;
|
|
Datum arg;
|
|
} ExprContext_CB;
|
|
|
|
/* ----------------
|
|
* ExprContext
|
|
*
|
|
* This class holds the "current context" information
|
|
* needed to evaluate expressions for doing tuple qualifications
|
|
* and tuple projections. For example, if an expression refers
|
|
* to an attribute in the current inner tuple then we need to know
|
|
* what the current inner tuple is and so we look at the expression
|
|
* context.
|
|
*
|
|
* There are two memory contexts associated with an ExprContext:
|
|
* * ecxt_per_query_memory is a query-lifespan context, typically the same
|
|
* context the ExprContext node itself is allocated in. This context
|
|
* can be used for purposes such as storing function call cache info.
|
|
* * ecxt_per_tuple_memory is a short-term context for expression results.
|
|
* As the name suggests, it will typically be reset once per tuple,
|
|
* before we begin to evaluate expressions for that tuple. Each
|
|
* ExprContext normally has its very own per-tuple memory context.
|
|
*
|
|
* CurrentMemoryContext should be set to ecxt_per_tuple_memory before
|
|
* calling ExecEvalExpr() --- see ExecEvalExprSwitchContext().
|
|
* ----------------
|
|
*/
|
|
struct PLpgSQL_execstate;
|
|
|
|
typedef struct ExprContext {
|
|
NodeTag type;
|
|
|
|
/* Tuples that Var nodes in expression may refer to */
|
|
TupleTableSlot* ecxt_scantuple;
|
|
TupleTableSlot* ecxt_innertuple;
|
|
TupleTableSlot* ecxt_outertuple;
|
|
|
|
/* Memory contexts for expression evaluation --- see notes above */
|
|
MemoryContext ecxt_per_query_memory;
|
|
MemoryContext ecxt_per_tuple_memory;
|
|
|
|
/* Values to substitute for Param nodes in expression */
|
|
ParamExecData* ecxt_param_exec_vals; /* for PARAM_EXEC params */
|
|
ParamListInfo ecxt_param_list_info; /* for other param types */
|
|
|
|
/*
|
|
* Values to substitute for Aggref nodes in the expressions of an Agg
|
|
* node, or for WindowFunc nodes within a WindowAgg node.
|
|
*/
|
|
Datum* ecxt_aggvalues; /* precomputed values for aggs/windowfuncs */
|
|
bool* ecxt_aggnulls; /* null flags for aggs/windowfuncs */
|
|
|
|
/* Value to substitute for CaseTestExpr nodes in expression */
|
|
Datum caseValue_datum;
|
|
bool caseValue_isNull;
|
|
|
|
ScalarVector* caseValue_vector;
|
|
|
|
/* Value to substitute for CoerceToDomainValue nodes in expression */
|
|
Datum domainValue_datum;
|
|
bool domainValue_isNull;
|
|
|
|
/* Link to containing EState (NULL if a standalone ExprContext) */
|
|
struct EState* ecxt_estate;
|
|
|
|
/* Functions to call back when ExprContext is shut down */
|
|
ExprContext_CB* ecxt_callbacks;
|
|
|
|
// vector specific fields
|
|
// consider share space with row fields
|
|
//
|
|
VectorBatch* ecxt_scanbatch;
|
|
VectorBatch* ecxt_innerbatch;
|
|
VectorBatch* ecxt_outerbatch;
|
|
|
|
// Batch to substitute for Aggref nodes in the expression of an VecAgg node
|
|
//
|
|
VectorBatch* ecxt_aggbatch;
|
|
|
|
/*
|
|
* mark the real rows for expression cluster, all the results' m_rows generated by
|
|
* vec-expression are aligned by econtext->align_rows
|
|
*/
|
|
int align_rows;
|
|
|
|
bool m_fUseSelection; // Shall we use selection vector?
|
|
ScalarVector* qual_results;
|
|
ScalarVector* boolVector;
|
|
bool is_cursor;
|
|
Cursor_Data cursor_data;
|
|
int dno;
|
|
PLpgSQL_execstate* plpgsql_estate;
|
|
|
|
bool hasSetResultStore;
|
|
/*
|
|
* For vector set-result function.
|
|
*/
|
|
bool have_vec_set_fun;
|
|
bool* vec_fun_sel; // selection for vector set-result function.
|
|
int current_row;
|
|
bool can_ignore; // indicates whether ERROR can be ignored when type casting
|
|
|
|
RightRefState* rightRefState;
|
|
#ifdef USE_SPQ
|
|
OffsetNumber cached_root_offsets[MaxHeapTuplesPerPage];
|
|
BlockNumber cached_blkno;
|
|
#endif
|
|
} ExprContext;
|
|
|
|
/*
|
|
* Set-result status used when evaluating functions potentially returning a
|
|
* set.
|
|
*/
|
|
typedef enum {
|
|
ExprSingleResult, /* expression does not return a set */
|
|
ExprMultipleResult, /* this result is an element of a set */
|
|
ExprEndResult /* there are no more elements in the set */
|
|
} ExprDoneCond;
|
|
|
|
/*
|
|
* Return modes for functions returning sets. Note values must be chosen
|
|
* as separate bits so that a bitmask can be formed to indicate supported
|
|
* modes. SFRM_Materialize_Random and SFRM_Materialize_Preferred are
|
|
* auxiliary flags about SFRM_Materialize mode, rather than separate modes.
|
|
*/
|
|
typedef enum {
|
|
SFRM_ValuePerCall = 0x01, /* one value returned per call */
|
|
SFRM_Materialize = 0x02, /* result set instantiated in Tuplestore */
|
|
SFRM_Materialize_Random = 0x04, /* Tuplestore needs randomAccess */
|
|
SFRM_Materialize_Preferred = 0x08 /* caller prefers Tuplestore */
|
|
} SetFunctionReturnMode;
|
|
|
|
/*
|
|
* When calling a function that might return a set (multiple rows),
|
|
* a node of this type is passed as fcinfo->resultinfo to allow
|
|
* return status to be passed back. A function returning set should
|
|
* raise an error if no such resultinfo is provided.
|
|
*/
|
|
typedef struct ReturnSetInfo {
|
|
NodeTag type;
|
|
/* values set by caller: */
|
|
ExprContext* econtext; /* context function is being called in */
|
|
TupleDesc expectedDesc; /* tuple descriptor expected by caller */
|
|
int allowedModes; /* bitmask: return modes caller can handle */
|
|
/* result status from function (but pre-initialized by caller): */
|
|
SetFunctionReturnMode returnMode; /* actual return mode */
|
|
ExprDoneCond isDone; /* status for ValuePerCall mode */
|
|
/* fields filled by function in Materialize return mode: */
|
|
Tuplestorestate* setResult; /* holds the complete returned tuple set */
|
|
TupleDesc setDesc; /* actual descriptor for returned tuples */
|
|
} ReturnSetInfo;
|
|
|
|
/*
|
|
* Function pointer which will be used by LLVM assemble. The created IR functions
|
|
* will be added to the actual machine code.
|
|
*/
|
|
typedef ScalarVector* (*vecqual_func)(ExprContext* econtext);
|
|
|
|
/* ----------------
|
|
* JunkFilter
|
|
*
|
|
* This class is used to store information regarding junk attributes.
|
|
* A junk attribute is an attribute in a tuple that is needed only for
|
|
* storing intermediate information in the executor, and does not belong
|
|
* in emitted tuples. For example, when we do an UPDATE query,
|
|
* the planner adds a "junk" entry to the targetlist so that the tuples
|
|
* returned to ExecutePlan() contain an extra attribute: the ctid of
|
|
* the tuple to be updated. This is needed to do the update, but we
|
|
* don't want the ctid to be part of the stored new tuple! So, we
|
|
* apply a "junk filter" to remove the junk attributes and form the
|
|
* real output tuple. The junkfilter code also provides routines to
|
|
* extract the values of the junk attribute(s) from the input tuple.
|
|
*
|
|
* targetList: the original target list (including junk attributes).
|
|
* cleanTupType: the tuple descriptor for the "clean" tuple (with
|
|
* junk attributes removed).
|
|
* cleanMap: A map with the correspondence between the non-junk
|
|
* attribute numbers of the "original" tuple and the
|
|
* attribute numbers of the "clean" tuple.
|
|
* resultSlot: tuple slot used to hold cleaned tuple.
|
|
* junkAttNo: not used by junkfilter code. Can be used by caller
|
|
* to remember the attno of a specific junk attribute
|
|
* (nodeModifyTable.c keeps the "ctid" or "wholerow"
|
|
* attno here).
|
|
* ----------------
|
|
*/
|
|
typedef struct JunkFilter {
|
|
NodeTag type;
|
|
List* jf_targetList;
|
|
TupleDesc jf_cleanTupType;
|
|
AttrNumber* jf_cleanMap;
|
|
TupleTableSlot* jf_resultSlot;
|
|
AttrNumber jf_junkAttNo;
|
|
#ifdef PGXC
|
|
/*
|
|
* Similar to jf_junkAttNo that is used for ctid, we also need xc_node_id
|
|
* and wholerow junk attribute numbers to be saved here. In XC, we need
|
|
* multiple junk attributes at the same time, so just jf_junkAttNo is not
|
|
* enough. In PG, jf_junkAttNo is used either for ctid or for wholerow,
|
|
* it does not need both of them at the same time; ctid is used for physical
|
|
* relations while wholerow is used for views.
|
|
*/
|
|
AttrNumber jf_xc_node_id;
|
|
AttrNumber jf_xc_wholerow;
|
|
AttrNumber jf_xc_part_id;
|
|
AttrNumber jf_xc_bucket_id;
|
|
List* jf_primary_keys;
|
|
#endif
|
|
} JunkFilter;
|
|
|
|
typedef struct MergeState {
|
|
/* List of MERGE MATCHED action states */
|
|
List* matchedActionStates;
|
|
/* List of MERGE NOT MATCHED action states */
|
|
List* notMatchedActionStates;
|
|
} MergeState;
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Expression State Trees
|
|
*
|
|
* Each executable expression tree has a parallel ExprState tree.
|
|
*
|
|
* Unlike PlanState, there is not an exact one-for-one correspondence between
|
|
* ExprState node types and Expr node types. Many Expr node types have no
|
|
* need for node-type-specific run-time state, and so they can use plain
|
|
* ExprState or GenericExprState as their associated ExprState node type.
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
|
|
/* ----------------
|
|
* ExprState node
|
|
*
|
|
* ExprState is the common superclass for all ExprState-type nodes.
|
|
*
|
|
* It can also be instantiated directly for leaf Expr nodes that need no
|
|
* local run-time state (such as Var, Const, or Param).
|
|
*
|
|
* To save on dispatch overhead, each ExprState node contains a function
|
|
* pointer to the routine to execute to evaluate the node.
|
|
* ----------------
|
|
*/
|
|
struct ExprState;
|
|
|
|
typedef Datum (*ExprStateEvalFunc)(ExprState* expression, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone);
|
|
typedef ScalarVector* (*VectorExprFun)(
|
|
ExprState* expression, ExprContext* econtext, bool* selVector, ScalarVector* inputVector, ExprDoneCond* isDone);
|
|
|
|
typedef void* (*exprFakeCodeGenSig)(void*);
|
|
|
|
/* Bits in ExprState->flags (see also execExpr.h for private flag bits): */
|
|
/* expression is for use with ExecQual() */
|
|
#define EEO_FLAG_IS_QUAL (1 << 0)
|
|
|
|
struct ExprState {
|
|
NodeTag type;
|
|
|
|
uint8 flags; /* bitmask of EEO_FLAG_* bits, see above */
|
|
|
|
/*
|
|
* Storage for result value of a scalar expression, or for individual
|
|
* column results within expressions built by ExecBuildProjectionInfo().
|
|
*/
|
|
bool resnull;
|
|
Datum resvalue;
|
|
|
|
/*
|
|
* If projecting a tuple result, this slot holds the result; else NULL.
|
|
*/
|
|
TupleTableSlot *resultslot;
|
|
|
|
/*
|
|
* Instructions to compute expression's return value.
|
|
*/
|
|
struct ExprEvalStep *steps;
|
|
|
|
/*
|
|
* Function that actually evaluates the expression. This can be set to
|
|
* different values depending on the complexity of the expression.
|
|
*/
|
|
ExprStateEvalFunc evalfunc;
|
|
|
|
/* original expression tree, for debugging only */
|
|
Expr *expr;
|
|
/* private state for an evalfunc */
|
|
void *evalfunc_private;
|
|
|
|
/*
|
|
* XXX: following fields only needed during "compilation" (ExecInitExpr);
|
|
* could be thrown away afterwards.
|
|
*/
|
|
|
|
int steps_len; /* number of steps currently */
|
|
int steps_alloc; /* allocated length of steps array */
|
|
|
|
struct PlanState *parent; /* parent PlanState node, if any */
|
|
|
|
Datum *innermost_caseval;
|
|
bool *innermost_casenull;
|
|
|
|
Datum *innermost_domainval;
|
|
bool *innermost_domainnull;
|
|
|
|
ListCell *current_targetentry;
|
|
|
|
// vectorized evaluator
|
|
//
|
|
VectorExprFun vecExprFun;
|
|
|
|
exprFakeCodeGenSig exprCodeGen; /* routine to run llvm assembler function */
|
|
|
|
bool is_flt_frame; /*Indicates whether it is a flattened expr frame */
|
|
ScalarVector tmpVector;
|
|
|
|
Oid resultType;
|
|
};
|
|
|
|
/* ----------------
|
|
* ProjectionInfo node information
|
|
*
|
|
* This is all the information needed to perform projections ---
|
|
* that is, form new tuples by evaluation of targetlist expressions.
|
|
* Nodes which need to do projections create one of these.
|
|
*
|
|
* ExecProject() evaluates the tlist, forms a tuple, and stores it
|
|
* in the given slot. Note that the result will be a "virtual" tuple
|
|
* unless ExecMaterializeSlot() is then called to force it to be
|
|
* converted to a physical tuple. The slot must have a tupledesc
|
|
* that matches the output of the tlist!
|
|
*
|
|
* The planner very often produces tlists that consist entirely of
|
|
* simple Var references (lower levels of a plan tree almost always
|
|
* look like that). And top-level tlists are often mostly Vars too.
|
|
* We therefore optimize execution of simple-Var tlist entries.
|
|
* The pi_targetlist list actually contains only the tlist entries that
|
|
* aren't simple Vars, while those that are Vars are processed using the
|
|
* varSlotOffsets/varNumbers/varOutputCols arrays.
|
|
*
|
|
* The lastXXXVar fields are used to optimize fetching of fields from
|
|
* input tuples: they let us do a slot_getsomeattrs() call to ensure
|
|
* that all needed attributes are extracted in one pass.
|
|
*
|
|
* targetlist target list for projection (non-Var expressions only)
|
|
* exprContext expression context in which to evaluate targetlist
|
|
* slot slot to place projection result in
|
|
* itemIsDone workspace array for ExecProject
|
|
* directMap true if varOutputCols[] is an identity map
|
|
* numSimpleVars number of simple Vars found in original tlist
|
|
* varSlotOffsets array indicating which slot each simple Var is from
|
|
* varNumbers array containing input attr numbers of simple Vars
|
|
* varOutputCols array containing output attr numbers of simple Vars
|
|
* lastInnerVar highest attnum from inner tuple slot (0 if none)
|
|
* lastOuterVar highest attnum from outer tuple slot (0 if none)
|
|
* lastScanVar highest attnum from scan tuple slot (0 if none)
|
|
* pi_maxOrmin column table optimize, indicate if get this column's max or min.
|
|
* ----------------
|
|
*/
|
|
typedef bool (*vectarget_func)(ExprContext* econtext, VectorBatch* pBatch);
|
|
typedef struct ProjectionInfo {
|
|
NodeTag type;
|
|
List* pi_targetlist;
|
|
/* instructions to evaluate projection */
|
|
ExprState pi_state;
|
|
/* expression context in which to evaluate expression */
|
|
ExprContext* pi_exprContext;
|
|
TupleTableSlot* pi_slot;
|
|
ExprDoneCond* pi_itemIsDone;
|
|
bool pi_directMap;
|
|
bool pi_topPlan; /* Whether the outermost layer query */
|
|
int pi_numSimpleVars;
|
|
int* pi_varSlotOffsets;
|
|
int* pi_varNumbers;
|
|
int* pi_varOutputCols;
|
|
int pi_lastInnerVar;
|
|
int pi_lastOuterVar;
|
|
int pi_lastScanVar;
|
|
List* pi_projectVarNumbers;
|
|
List* pi_acessedVarNumbers;
|
|
List* pi_sysAttrList;
|
|
List* pi_lateAceessVarNumbers;
|
|
List* pi_maxOrmin;
|
|
List* pi_PackTCopyVars; /* VarList to record those columns what we need to move */
|
|
List* pi_PackLateAccessVarNumbers; /*VarList to record those columns what we need to move in late read cstore
|
|
scan.*/
|
|
bool pi_const;
|
|
ExprDoneCond* pi_vec_itemIsDone;
|
|
VectorBatch* pi_batch;
|
|
vectarget_func jitted_vectarget; /* LLVM function pointer to point to the codegened targetlist expr function */
|
|
VectorBatch* pi_setFuncBatch;
|
|
bool isUpsertHasRightRef;
|
|
} ProjectionInfo;
|
|
|
|
/* ----------------
|
|
* ResultRelInfo information
|
|
*
|
|
* Whenever we update an existing relation, we have to
|
|
* update indices on the relation, and perhaps also fire triggers.
|
|
* The ResultRelInfo class is used to hold all the information needed
|
|
* about a result relation, including indices.. -cim 10/15/89
|
|
*
|
|
* RangeTableIndex result relation's range table index
|
|
* RelationDesc relation descriptor for result relation
|
|
* NumIndices # of indices existing on result relation
|
|
* ri_ContainGPI indices whether contain global parition index
|
|
* IndexRelationDescs array of relation descriptors for indices
|
|
* IndexRelationInfo array of key/attr info for indices
|
|
* TrigDesc triggers to be fired, if any
|
|
* TrigFunctions cached lookup info for trigger functions
|
|
* TrigWhenExprs array of trigger WHEN expr states
|
|
* TrigInstrument optional runtime measurements for triggers
|
|
* FdwRoutine FDW callback functions, if foreign table
|
|
* FdwState available to save private state of FDW
|
|
* ConstraintExprs array of constraint-checking expr states
|
|
* junkFilter for removing junk attributes from tuples
|
|
* projectReturning for computing a RETURNING list
|
|
* updateProj for computing a UPSERT update list
|
|
* WithCheckOptions list of WithCheckOption's for views
|
|
* WithCheckOptionExprs list of WithCheckOption expr states
|
|
* ----------------
|
|
*/
|
|
typedef struct ResultRelInfo {
|
|
NodeTag type;
|
|
Index ri_RangeTableIndex;
|
|
Relation ri_RelationDesc;
|
|
int ri_NumIndices;
|
|
bool ri_ContainGPI;
|
|
RelationPtr ri_IndexRelationDescs;
|
|
IndexInfo** ri_IndexRelationInfo;
|
|
TriggerDesc* ri_TrigDesc;
|
|
FmgrInfo* ri_TrigFunctions;
|
|
List** ri_TrigWhenExprs;
|
|
Instrumentation* ri_TrigInstrument;
|
|
struct FdwRoutine* ri_FdwRoutine;
|
|
void* ri_FdwState;
|
|
List** ri_ConstraintExprs;
|
|
JunkFilter* ri_junkFilter;
|
|
AttrNumber ri_partOidAttNum;
|
|
AttrNumber ri_bucketIdAttNum;
|
|
ProjectionInfo* ri_projectReturning;
|
|
|
|
/* for running MERGE on this result relation */
|
|
MergeState* ri_mergeState;
|
|
|
|
/*
|
|
* While executing MERGE, the target relation is processed twice; once
|
|
* as a target relation and once to run a join between the target and the
|
|
* source. We generate two different RTEs for these two purposes, one with
|
|
* rte->inh set to false and other with rte->inh set to true.
|
|
*
|
|
* Since the plan re-evaluated by EvalPlanQual uses the join RTE, we must
|
|
* install the updated tuple in the scan corresponding to that RTE. The
|
|
* following member tracks the index of the second RTE for EvalPlanQual
|
|
* purposes. ri_mergeTargetRTI is non-zero only when MERGE is in-progress.
|
|
* We use ri_mergeTargetRTI to run EvalPlanQual for MERGE and
|
|
* ri_RangeTableIndex elsewhere.
|
|
*/
|
|
Index ri_mergeTargetRTI;
|
|
ProjectionInfo* ri_updateProj;
|
|
|
|
/* array of stored generated columns expr states */
|
|
ExprState **ri_GeneratedExprs;
|
|
|
|
/* array of stored UpdateExpr columns expr states */
|
|
ExprState **ri_UpdatedExprs;
|
|
|
|
/* number of stored generated columns we need to compute */
|
|
int ri_NumGeneratedNeeded;
|
|
/* number of stored UpdateExpr columns we need to compute */
|
|
int ri_NumUpdatedNeeded;
|
|
List* ri_WithCheckOptions;
|
|
List* ri_WithCheckOptionExprs;
|
|
|
|
ProjectionInfo* ri_updateWhere; /* list of ON CONFLICT DO UPDATE exprs (qual)*/
|
|
#ifdef USE_SPQ
|
|
AttrNumber ri_actionAttno; /* is this an INSERT or DELETE ? */
|
|
#endif
|
|
|
|
/* number of the unusable index*/
|
|
int ri_NumUnusableIndices;
|
|
RelationPtr ri_UnusableIndexRelationDescs;
|
|
IndexInfo** ri_UnusableIndexRelationInfo;
|
|
} ResultRelInfo;
|
|
|
|
/* bloom filter controller */
|
|
typedef struct BloomFilterControl {
|
|
filter::BloomFilter** bfarray; /* bloom filter array. */
|
|
int array_size; /* bloom filter array size. */
|
|
} BloomFilterControl;
|
|
|
|
#define InvalidBktId (-1) /* invalid hash-bucket id */
|
|
|
|
/* ----------------
|
|
* EState information
|
|
*
|
|
* Master working state for an Executor invocation
|
|
* ----------------
|
|
*/
|
|
typedef struct EState {
|
|
NodeTag type;
|
|
|
|
/* Basic state for all query types: */
|
|
ScanDirection es_direction; /* current scan direction */
|
|
Snapshot es_snapshot; /* time qual to use */
|
|
Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
|
|
List* es_range_table; /* List of RangeTblEntry */
|
|
PlannedStmt* es_plannedstmt; /* link to top of plan tree */
|
|
|
|
JunkFilter* es_junkFilter; /* top-level junk filter, if any */
|
|
|
|
/* If query can insert/delete tuples, the command ID to mark them with */
|
|
CommandId es_output_cid;
|
|
|
|
bool es_is_flt_frame; /*Indicates whether it is a flattened expr frame */
|
|
|
|
/* Info about target table(s) for insert/update/delete queries: */
|
|
ResultRelInfo* es_result_relations; /* array of ResultRelInfos */
|
|
int es_num_result_relations; /* length of array */
|
|
ResultRelInfo* es_result_relation_info; /* currently active array elt */
|
|
|
|
Relation esCurrentPartition;
|
|
HTAB* esfRelations; /* do the update,delete , cache the Relation which get from partitionGetRelation */
|
|
#ifdef PGXC
|
|
struct PlanState* es_result_remoterel; /* currently active remote rel */
|
|
struct PlanState* es_result_insert_remoterel; /* currently active remote rel */
|
|
struct PlanState* es_result_update_remoterel; /* currently active remote rel */
|
|
struct PlanState* es_result_delete_remoterel; /* currently active remote rel */
|
|
#endif
|
|
|
|
/* Stuff used for firing triggers: */
|
|
List* es_trig_target_relations; /* trigger-only ResultRelInfos */
|
|
TupleTableSlot* es_trig_tuple_slot; /* for trigger output tuples */
|
|
TupleTableSlot* es_trig_oldtup_slot; /* for TriggerEnabled */
|
|
TupleTableSlot* es_trig_newtup_slot; /* for TriggerEnabled */
|
|
|
|
/* Parameter info: */
|
|
ParamListInfo es_param_list_info; /* values of external params */
|
|
ParamExecData* es_param_exec_vals; /* values of internal params */
|
|
|
|
/* Other working state: */
|
|
MemoryContext es_query_cxt; /* per-query context in which EState lives */
|
|
MemoryContext es_const_query_cxt; /* const per-query context used to create node context */
|
|
|
|
List* es_tupleTable; /* List of TupleTableSlots */
|
|
|
|
List* es_rowMarks; /* List of ExecRowMarks */
|
|
|
|
List *es_modifiedRowHash; /* List of prevHash of modified rows */
|
|
|
|
uint64 es_processed; /* # of tuples processed */
|
|
|
|
uint64 deleteLimitCount; /* delete Limit */
|
|
|
|
uint64 es_last_processed; /* last value of es_processed for ModifyTable plan*/
|
|
|
|
Oid es_lastoid; /* last oid processed (by INSERT) */
|
|
|
|
int es_top_eflags; /* eflags passed to ExecutorStart */
|
|
int es_instrument; /* OR of InstrumentOption flags */
|
|
bool es_finished; /* true when ExecutorFinish is done */
|
|
|
|
List* es_exprcontexts; /* List of ExprContexts within EState */
|
|
|
|
List* es_subplanstates; /* List of PlanState for SubPlans */
|
|
|
|
List* es_auxmodifytables; /* List of secondary ModifyTableStates */
|
|
|
|
List* es_remotequerystates; /* List of RemoteQueryStates */
|
|
|
|
/*
|
|
* this ExprContext is for per-output-tuple operations, such as constraint
|
|
* checks and index-value computations. It will be reset for each output
|
|
* tuple. Note that it will be created only if needed.
|
|
*/
|
|
ExprContext* es_per_tuple_exprcontext;
|
|
|
|
/*
|
|
* These fields are for re-evaluating plan quals when an updated tuple is
|
|
* substituted in READ COMMITTED mode. es_epqTuple[] contains tuples that
|
|
* scan plan nodes should return instead of whatever they'd normally
|
|
* return, or NULL if nothing to return; es_epqTupleSet[] is true if a
|
|
* particular array entry is valid; and es_epqScanDone[] is state to
|
|
* remember if the tuple has been returned already. Arrays are of size
|
|
* list_length(es_range_table) and are indexed by scan node scanrelid - 1.
|
|
*/
|
|
Tuple* es_epqTuple; /* array of EPQ substitute tuples */
|
|
TupleTableSlot** es_epqTupleSlot;
|
|
bool* es_epqTupleSet; /* true if EPQ tuple is provided */
|
|
bool* es_epqScanDone; /* true if EPQ tuple has been fetched */
|
|
|
|
List* es_subplan_ids;
|
|
bool es_skip_early_free; /* true if we don't apply early free mechanisim, especially for subplan */
|
|
/* true if we don't apply early-free-consumer mechanisim, especially for subplan */
|
|
bool es_skip_early_deinit_consumer;
|
|
bool es_under_subplan; /* true if operator is under a subplan */
|
|
List* es_material_of_subplan; /* List of Materialize operator of subplan */
|
|
bool es_recursive_next_iteration; /* true if under recursive-stream and need to rescan. */
|
|
|
|
/* data redistribution for DFS table.
|
|
* dataDestRelIndex is index into the range table. This variable
|
|
* will take effect on data redistribution state.
|
|
*/
|
|
Index dataDestRelIndex;
|
|
|
|
BloomFilterControl es_bloom_filter; /* bloom filter controller */
|
|
|
|
bool es_can_realtime_statistics; /* true if can realime statistics */
|
|
bool es_can_history_statistics; /* true if can history statistics */
|
|
|
|
bool isRowTriggerShippable; /* true if all row triggers are shippable. */
|
|
#ifdef ENABLE_MOT
|
|
JitExec::MotJitContext* mot_jit_context; /* MOT JIT context required for executing LLVM jitted code */
|
|
#endif
|
|
|
|
PruningResult* pruningResult;
|
|
bool have_current_xact_date; /* Check whether dirty reads exist in the cursor rollback scenario. */
|
|
int128 first_autoinc; /* autoinc has increased during this execution */
|
|
int result_rel_index; /* which result_rel_info to be excuted when multiple-relation modified. */
|
|
int128 cur_insert_autoinc;
|
|
int128 next_autoinc;
|
|
#ifdef USE_SPQ
|
|
List *es_sharenode;
|
|
#endif
|
|
} EState;
|
|
|
|
/*
|
|
* ExecRowMark -
|
|
* runtime representation of FOR UPDATE/SHARE clauses
|
|
*
|
|
* When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we should have an
|
|
* ExecRowMark for each non-target relation in the query (except inheritance
|
|
* parent RTEs, which can be ignored at runtime). See PlanRowMark for details
|
|
* about most of the fields. In addition to fields directly derived from
|
|
* PlanRowMark, we store curCtid, which is used by the WHERE CURRENT OF code.
|
|
*
|
|
* EState->es_rowMarks is a list of these structs.
|
|
*/
|
|
typedef struct ExecRowMark {
|
|
Relation relation; /* opened and suitably locked relation */
|
|
Index rti; /* its range table index */
|
|
Index prti; /* parent range table index, if child */
|
|
Index rowmarkId; /* unique identifier for resjunk columns */
|
|
RowMarkType markType; /* see enum in nodes/plannodes.h */
|
|
LockWaitPolicy waitPolicy; /* NOWAIT option */
|
|
int waitSec; /* WAIT time Sec */
|
|
ItemPointerData curCtid; /* ctid of currently locked tuple, if any */
|
|
int numAttrs; /* number of attributes in subplan */
|
|
} ExecRowMark;
|
|
|
|
#define PREV_HASH_LEN 36
|
|
/*
|
|
* ExecModifiedRowHash -
|
|
* store previous hash of modified row.
|
|
*
|
|
*/
|
|
typedef struct ExecModifiedRowHash {
|
|
char hash[PREV_HASH_LEN]; /* value of previous hash */
|
|
} ExecModifiedRowHash;
|
|
|
|
/*
|
|
* ExecAuxRowMark -
|
|
* additional runtime representation of FOR UPDATE/SHARE clauses
|
|
*
|
|
* Each LockRows and ModifyTable node keeps a list of the rowmarks it needs to
|
|
* deal with. In addition to a pointer to the related entry in es_rowMarks,
|
|
* this struct carries the column number(s) of the resjunk columns associated
|
|
* with the rowmark (see comments for PlanRowMark for more detail). In the
|
|
* case of ModifyTable, there has to be a separate ExecAuxRowMark list for
|
|
* each child plan, because the resjunk columns could be at different physical
|
|
* column positions in different subplans.
|
|
*/
|
|
typedef struct ExecAuxRowMark {
|
|
ExecRowMark* rowmark; /* related entry in es_rowMarks */
|
|
AttrNumber ctidAttNo; /* resno of ctid junk attribute, if any */
|
|
AttrNumber toidAttNo; /* resno of tableoid junk attribute, if any */
|
|
AttrNumber tbidAttNo; /* resno of bucketid junk attribute, if any */
|
|
AttrNumber wholeAttNo; /* resno of whole-row junk attribute, if any */
|
|
} ExecAuxRowMark;
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Tuple Hash Tables
|
|
*
|
|
* All-in-memory tuple hash tables are used for a number of purposes.
|
|
*
|
|
* Note: tab_hash_funcs are for the key datatype(s) stored in the table,
|
|
* and tab_eq_funcs are non-cross-type equality operators for those types.
|
|
* Normally these are the only functions used, but FindTupleHashEntry()
|
|
* supports searching a hashtable using cross-data-type hashing. For that,
|
|
* the caller must supply hash functions for the LHS datatype as well as
|
|
* the cross-type equality operators to use. in_hash_funcs and cur_eq_funcs
|
|
* are set to point to the caller's function arrays while doing such a search.
|
|
* During LookupTupleHashEntry(), they point to tab_hash_funcs and
|
|
* tab_eq_funcs respectively.
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
typedef struct TupleHashEntryData* TupleHashEntry;
|
|
typedef struct TupleHashTableData* TupleHashTable;
|
|
|
|
typedef struct TupleHashEntryData {
|
|
/* firstTuple must be the first field in this struct! */
|
|
MinimalTuple firstTuple; /* copy of first tuple in this group */
|
|
/* there may be additional data beyond the end of this struct */
|
|
} TupleHashEntryData; /* VARIABLE LENGTH STRUCT */
|
|
|
|
typedef struct TupleHashTableData {
|
|
HTAB* hashtab; /* underlying dynahash table */
|
|
int numCols; /* number of columns in lookup key */
|
|
AttrNumber* keyColIdx; /* attr numbers of key columns */
|
|
FmgrInfo* tab_hash_funcs; /* hash functions for table datatype(s) */
|
|
FmgrInfo* tab_eq_funcs; /* equality functions for table datatype(s) */
|
|
MemoryContext tablecxt; /* memory context containing table */
|
|
MemoryContext tempcxt; /* context for function evaluations */
|
|
Size entrysize; /* actual size to make each hash entry */
|
|
TupleTableSlot* tableslot; /* slot for referencing table entries */
|
|
/* The following fields are set transiently for each table search: */
|
|
TupleTableSlot* inputslot; /* current input tuple's slot */
|
|
FmgrInfo* in_hash_funcs; /* hash functions for input datatype(s) */
|
|
FmgrInfo* cur_eq_funcs; /* equality functions for input vs. table */
|
|
int64 width; /* records total width in memory */
|
|
bool add_width; /* if width should be added */
|
|
bool causedBySysRes; /* the batch increase caused by system resources limit? */
|
|
Oid *tab_collations; /* collations for hash and comparison */
|
|
} TupleHashTableData;
|
|
|
|
typedef HASH_SEQ_STATUS TupleHashIterator;
|
|
|
|
/*
|
|
* Use InitTupleHashIterator/TermTupleHashIterator for a read/write scan.
|
|
* Use ResetTupleHashIterator if the table can be frozen (in this case no
|
|
* explicit scan termination is needed).
|
|
*/
|
|
#define InitTupleHashIterator(htable, iter) hash_seq_init(iter, (htable)->hashtab)
|
|
#define TermTupleHashIterator(iter) hash_seq_term(iter)
|
|
#define ResetTupleHashIterator(htable, iter) \
|
|
do { \
|
|
hash_freeze((htable)->hashtab); \
|
|
hash_seq_init(iter, (htable)->hashtab); \
|
|
} while (0)
|
|
#define ScanTupleHashTable(iter) ((TupleHashEntry)hash_seq_search(iter))
|
|
|
|
/* ----------------
|
|
* GenericExprState node
|
|
*
|
|
* This is used for Expr node types that need no local run-time state,
|
|
* but have one child Expr node.
|
|
* ----------------
|
|
*/
|
|
typedef struct GenericExprState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* state of my child node */
|
|
} GenericExprState;
|
|
|
|
/* ----------------
|
|
* WholeRowVarExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct WholeRowVarExprState {
|
|
ExprState xprstate;
|
|
struct PlanState* parent; /* parent PlanState, or NULL if none */
|
|
JunkFilter* wrv_junkFilter; /* JunkFilter to remove resjunk cols */
|
|
} WholeRowVarExprState;
|
|
|
|
/* ----------------
|
|
* AggrefExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct AggrefExprState {
|
|
ExprState xprstate;
|
|
Aggref *aggref; /* expression plan node */
|
|
List* aggdirectargs; /* states of direct-argument expressions */
|
|
List* args; /* states of argument expressions */
|
|
ExprState* aggfilter; /* state of FILTER expression, if any */
|
|
int aggno; /* ID number for agg within its plan node */
|
|
|
|
// Vectorized aggregation fields
|
|
//
|
|
int m_htbOffset; // offset in the hash table
|
|
} AggrefExprState;
|
|
|
|
/* ----------------
|
|
* WindowFuncExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct WindowFuncExprState {
|
|
ExprState xprstate;
|
|
WindowFunc *wfunc; /* expression plan node */
|
|
List* args; /* states of argument expressions */
|
|
int wfuncno; /* ID number for wfunc within its plan node */
|
|
|
|
// Vectorized aggregation fields
|
|
//
|
|
ScalarVector* m_resultVector;
|
|
} WindowFuncExprState;
|
|
|
|
|
|
/* ----------------
|
|
* ArrayRefExprState node
|
|
*
|
|
* Note: array types can be fixed-length (typlen > 0), but only when the
|
|
* element type is itself fixed-length. Otherwise they are varlena structures
|
|
* and have typlen = -1. In any case, an array type is never pass-by-value.
|
|
* ----------------
|
|
*/
|
|
typedef struct ArrayRefExprState {
|
|
ExprState xprstate;
|
|
List* refupperindexpr; /* states for child nodes */
|
|
List* reflowerindexpr;
|
|
ExprState* refexpr;
|
|
ExprState* refassgnexpr;
|
|
int16 refattrlength; /* typlen of array type */
|
|
int16 refelemlength; /* typlen of the array element type */
|
|
bool refelembyval; /* is the element type pass-by-value? */
|
|
char refelemalign; /* typalign of the element type */
|
|
} ArrayRefExprState;
|
|
|
|
/* ----------------
|
|
* FuncExprState node
|
|
*
|
|
* Although named for FuncExpr, this is also used for OpExpr, DistinctExpr,
|
|
* and NullIf nodes; be careful to check what xprstate.expr is actually
|
|
* pointing at!
|
|
* ----------------
|
|
*/
|
|
typedef struct FuncExprState {
|
|
ExprState xprstate;
|
|
List* args; /* states of argument expressions */
|
|
char prokind;
|
|
/*
|
|
* Function manager's lookup info for the target function. If func.fn_oid
|
|
* is InvalidOid, we haven't initialized it yet (nor any of the following
|
|
* fields, except funcReturnsSet).
|
|
*/
|
|
FmgrInfo func;
|
|
|
|
/*
|
|
* For a set-returning function (SRF) that returns a tuplestore, we keep
|
|
* the tuplestore here and dole out the result rows one at a time. The
|
|
* slot holds the row currently being returned.
|
|
*/
|
|
Tuplestorestate* funcResultStore;
|
|
TupleTableSlot* funcResultSlot;
|
|
|
|
/*
|
|
* In some cases we need to compute a tuple descriptor for the function's
|
|
* output. If so, it's stored here.
|
|
*/
|
|
TupleDesc funcResultDesc;
|
|
bool funcReturnsTuple; /* valid when funcResultDesc isn't
|
|
* NULL */
|
|
|
|
/*
|
|
* Remember whether the function is declared to return a set. This is set
|
|
* by ExecInitExpr, and is valid even before the FmgrInfo is set up.
|
|
*/
|
|
bool funcReturnsSet;
|
|
|
|
/*
|
|
* setArgsValid is true when we are evaluating a set-returning function
|
|
* that uses value-per-call mode and we are in the middle of a call
|
|
* series; we want to pass the same argument values to the function again
|
|
* (and again, until it returns ExprEndResult). This indicates that
|
|
* fcinfo_data already contains valid argument data.
|
|
*/
|
|
bool setArgsValid;
|
|
|
|
bool setArgByVal; /* all args are by val? */
|
|
|
|
bool setHasSetArg;
|
|
|
|
bool is_plpgsql_func_with_outparam;
|
|
|
|
bool has_refcursor;
|
|
|
|
/*
|
|
* Flag to remember whether we have registered a shutdown callback for
|
|
* this FuncExprState. We do so only if funcResultStore or setArgsValid
|
|
* has been set at least once (since all the callback is for is to release
|
|
* the tuplestore or clear setArgsValid).
|
|
*/
|
|
bool shutdown_reg; /* a shutdown callback is registered */
|
|
|
|
/*
|
|
* Call parameter structure for the function. This has been initialized
|
|
* (by InitFunctionCallInfoData) if func.fn_oid is valid. It also saves
|
|
* argument values between calls, when setArgsValid is true.
|
|
*/
|
|
FunctionCallInfoData fcinfo_data;
|
|
|
|
ScalarVector* tmpVec;
|
|
bool vec_setHasSetArg; /* some argument returns a set */
|
|
} FuncExprState;
|
|
|
|
/* ----------------
|
|
* ScalarArrayOpExprState node
|
|
*
|
|
* This is a FuncExprState plus some additional data.
|
|
* ----------------
|
|
*/
|
|
typedef struct ScalarArrayOpExprState {
|
|
FuncExprState fxprstate;
|
|
/* Cached info about array element type */
|
|
Oid element_type;
|
|
int16 typlen;
|
|
bool typbyval;
|
|
char typalign;
|
|
bool* pSel; /* selection used to fast path of ALL/ANY */
|
|
ScalarVector *tmpVecLeft;
|
|
ScalarVector *tmpVecRight;
|
|
ScalarVector* tmpVec;
|
|
} ScalarArrayOpExprState;
|
|
|
|
/* ----------------
|
|
* BoolExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct BoolExprState {
|
|
ExprState xprstate;
|
|
List* args; /* states of argument expression(s) */
|
|
|
|
bool tmpSelection[BatchMaxSize]; // temp selection
|
|
} BoolExprState;
|
|
|
|
/* ----------------
|
|
* SubPlanState node
|
|
* ----------------
|
|
*/
|
|
typedef struct SubPlanState {
|
|
ExprState xprstate;
|
|
struct PlanState* planstate; /* subselect plan's state tree */
|
|
ExprState* testexpr; /* state of combining expression */
|
|
List* args; /* states of argument expression(s) */
|
|
ExprState* row_testexpr; /* for vector hash subplan */
|
|
HeapTuple curTuple; /* copy of most recent tuple from subplan */
|
|
Datum curArray; /* most recent array from ARRAY() subplan */
|
|
/* these are used when hashing the subselect's output: */
|
|
ProjectionInfo* projLeft; /* for projecting lefthand exprs */
|
|
ProjectionInfo* projRight; /* for projecting subselect output */
|
|
TupleHashTable hashtable; /* hash table for no-nulls subselect rows */
|
|
TupleHashTable hashnulls; /* hash table for rows with null(s) */
|
|
bool havehashrows; /* TRUE if hashtable is not empty */
|
|
bool havenullrows; /* TRUE if hashnulls is not empty */
|
|
MemoryContext hashtablecxt; /* memory context containing hash tables */
|
|
MemoryContext hashtempcxt; /* temp memory context for hash tables */
|
|
ExprContext* innerecontext; /* econtext for computing inner tuples */
|
|
AttrNumber* keyColIdx; /* control data for hash tables */
|
|
FmgrInfo* tab_hash_funcs; /* hash functions for table datatype(s) */
|
|
FmgrInfo* tab_eq_funcs; /* equality functions for table datatype(s) */
|
|
FmgrInfo* lhs_hash_funcs; /* hash functions for lefthand datatype(s) */
|
|
FmgrInfo* cur_eq_funcs; /* equality functions for LHS vs. table */
|
|
|
|
/* for vector engine */
|
|
int idx; /* a index to indicate which parameter to be pushed */
|
|
ScalarVector** pParamVectorArray; /* a array to store the param data */
|
|
ScalarVector** pParamVectorTmp; /* a temporary place to store the para data pointer */
|
|
bool* pSel; /* selection used to fast path */
|
|
VectorBatch* outExprBatch; /* a batch for only one row to store the para data for vector expr */
|
|
VectorBatch* innerExprBatch; /* a batch for only one row to store the para data for vector expr */
|
|
VectorBatch* scanExprBatch; /* a batch for only one row to store the para data for vector expr */
|
|
VectorBatch* aggExprBatch; /* a batch for only one row to store the para data for vector expr */
|
|
ScalarVector* tempvector; /* a temp vector for vector expression */
|
|
MemoryContext ecxt_per_batch_memory; /* memory contexts for one batch */
|
|
Oid *tab_collations; /* collations for hash and comparison */
|
|
} SubPlanState;
|
|
|
|
/* ----------------
|
|
* AlternativeSubPlanState node
|
|
* ----------------
|
|
*/
|
|
typedef struct AlternativeSubPlanState {
|
|
ExprState xprstate;
|
|
AlternativeSubPlan* subplan; /* expression plan node */
|
|
List* subplans; /* states of alternative subplans */
|
|
int active; /* list index of the one we're using */
|
|
} AlternativeSubPlanState;
|
|
|
|
/* ----------------
|
|
* FieldSelectState node
|
|
* ----------------
|
|
*/
|
|
typedef struct FieldSelectState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* input expression */
|
|
TupleDesc argdesc; /* tupdesc for most recent input */
|
|
} FieldSelectState;
|
|
|
|
/* ----------------
|
|
* FieldStoreState node
|
|
* ----------------
|
|
*/
|
|
typedef struct FieldStoreState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* input tuple value */
|
|
List* newvals; /* new value(s) for field(s) */
|
|
TupleDesc argdesc; /* tupdesc for most recent input */
|
|
} FieldStoreState;
|
|
|
|
/* ----------------
|
|
* CoerceViaIOState node
|
|
* ----------------
|
|
*/
|
|
typedef struct CoerceViaIOState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* input expression */
|
|
FmgrInfo outfunc; /* lookup info for source output function */
|
|
FmgrInfo infunc; /* lookup info for result input function */
|
|
Oid intypioparam; /* argument needed for input function */
|
|
} CoerceViaIOState;
|
|
|
|
/* ----------------
|
|
* ArrayCoerceExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct ArrayCoerceExprState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* input array value */
|
|
Oid resultelemtype; /* element type of result array */
|
|
FmgrInfo elemfunc; /* lookup info for element coercion function */
|
|
/* use struct pointer to avoid including array.h here */
|
|
struct ArrayMapState* amstate; /* workspace for array_map */
|
|
} ArrayCoerceExprState;
|
|
|
|
/* ----------------
|
|
* ConvertRowtypeExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct ConvertRowtypeExprState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* input tuple value */
|
|
TupleDesc indesc; /* tupdesc for source rowtype */
|
|
TupleDesc outdesc; /* tupdesc for result rowtype */
|
|
/* use "struct" so we needn't include tupconvert.h here */
|
|
struct TupleConversionMap* map;
|
|
bool initialized;
|
|
} ConvertRowtypeExprState;
|
|
|
|
/* ----------------
|
|
* CaseExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct CaseExprState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* implicit equality comparison argument */
|
|
List* args; /* the arguments (list of WHEN clauses) */
|
|
ExprState* defresult; /* the default result (ELSE clause) */
|
|
bool* matchedResult;
|
|
bool* localSel;
|
|
ScalarVector* save_vector;
|
|
} CaseExprState;
|
|
|
|
/* ----------------
|
|
* CaseWhenState node
|
|
* ----------------
|
|
*/
|
|
typedef struct CaseWhenState {
|
|
ExprState xprstate;
|
|
ExprState* expr; /* condition expression */
|
|
ExprState* result; /* substitution result */
|
|
} CaseWhenState;
|
|
|
|
/* ----------------
|
|
* ArrayExprState node
|
|
*
|
|
* Note: ARRAY[] expressions always produce varlena arrays, never fixed-length
|
|
* arrays.
|
|
* ----------------
|
|
*/
|
|
typedef struct ArrayExprState {
|
|
ExprState xprstate;
|
|
List* elements; /* states for child nodes */
|
|
int16 elemlength; /* typlen of the array element type */
|
|
bool elembyval; /* is the element type pass-by-value? */
|
|
char elemalign; /* typalign of the element type */
|
|
} ArrayExprState;
|
|
|
|
/* ----------------
|
|
* RowExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct RowExprState {
|
|
ExprState xprstate;
|
|
List* args; /* the arguments */
|
|
TupleDesc tupdesc; /* descriptor for result tuples */
|
|
VectorBatch* rowBatch; /* Save need columns */
|
|
} RowExprState;
|
|
|
|
/* ----------------
|
|
* RowCompareExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct RowCompareExprState {
|
|
ExprState xprstate;
|
|
List* largs; /* the left-hand input arguments */
|
|
List* rargs; /* the right-hand input arguments */
|
|
FmgrInfo* funcs; /* array of comparison function info */
|
|
Oid* collations; /* array of collations to use */
|
|
|
|
FunctionCallInfoData* cinfo;
|
|
|
|
ScalarVector* left_argvec; /* the left-hand input vector arguments */
|
|
ScalarVector* right_argvec; /* the right-hand input vector arguments */
|
|
ScalarVector* cmpresult; /* vector for compare result */
|
|
bool* pSel; /* vector for marking arguments to calculation */
|
|
} RowCompareExprState;
|
|
|
|
/* ----------------
|
|
* CoalesceExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct CoalesceExprState {
|
|
ExprState xprstate;
|
|
List* args; /* the arguments */
|
|
bool* pSel; /* selection used to fast path */
|
|
} CoalesceExprState;
|
|
|
|
/* ----------------
|
|
* MinMaxExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct MinMaxExprState {
|
|
ExprState xprstate;
|
|
List* args; /* the arguments */
|
|
FmgrInfo cfunc; /* lookup info for comparison func */
|
|
FunctionCallInfoData cinfo;
|
|
|
|
ScalarVector* argvec; /* eval arg results */
|
|
ScalarVector* cmpresult;
|
|
bool* pSel;
|
|
} MinMaxExprState;
|
|
|
|
/* ----------------
|
|
* XmlExprState node
|
|
* ----------------
|
|
*/
|
|
typedef struct XmlExprState {
|
|
ExprState xprstate;
|
|
List* named_args; /* ExprStates for named arguments */
|
|
List* args; /* ExprStates for other arguments */
|
|
} XmlExprState;
|
|
|
|
/* ----------------
|
|
* NullTestState node
|
|
* ----------------
|
|
*/
|
|
typedef struct NullTestState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* input expression */
|
|
/* used only if input is of composite type: */
|
|
TupleDesc argdesc; /* tupdesc for most recent input */
|
|
} NullTestState;
|
|
|
|
/* ----------------
|
|
* HashFilterState node
|
|
* ----------------
|
|
*/
|
|
typedef struct HashFilterState {
|
|
ExprState xprstate;
|
|
List* arg; /* input expression */
|
|
uint2* nodelist; /* Node indices where data is located */
|
|
uint2* bucketMap;
|
|
int bucketCnt;
|
|
} HashFilterState;
|
|
|
|
/* ----------------
|
|
* CoerceToDomainState node
|
|
* ----------------
|
|
*/
|
|
typedef struct CoerceToDomainState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* input expression */
|
|
/* Cached list of constraints that need to be checked */
|
|
List* constraints; /* list of DomainConstraintState nodes */
|
|
} CoerceToDomainState;
|
|
|
|
/*
|
|
* DomainConstraintState - one item to check during CoerceToDomain
|
|
*
|
|
* Note: this is just a Node, and not an ExprState, because it has no
|
|
* corresponding Expr to link to. Nonetheless it is part of an ExprState
|
|
* tree, so we give it a name following the xxxState convention.
|
|
*/
|
|
typedef enum DomainConstraintType { DOM_CONSTRAINT_NOTNULL, DOM_CONSTRAINT_CHECK } DomainConstraintType;
|
|
|
|
typedef struct DomainConstraintState {
|
|
NodeTag type;
|
|
DomainConstraintType constrainttype; /* constraint type */
|
|
char* name; /* name of constraint (for error msgs) */
|
|
Expr *check_node; /* for check, expr node,for flatten*/
|
|
ExprState *check_expr; /* for CHECK, a boolean expression */
|
|
} DomainConstraintState;
|
|
|
|
typedef struct HbktScanSlot {
|
|
int currSlot;
|
|
} HbktScanSlot;
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Executor State Trees
|
|
*
|
|
* An executing query has a PlanState tree paralleling the Plan tree
|
|
* that describes the plan.
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
typedef enum {
|
|
PST_None = 0,
|
|
PST_Norm = 1,
|
|
PST_Scan = 2
|
|
} PlanStubType;
|
|
|
|
struct PlanState;
|
|
|
|
/* ----------------
|
|
* ExecProcNodeMtd
|
|
*
|
|
* This is the method called by ExecProcNode to return the next tuple
|
|
* from an executor node. It returns NULL, or an empty TupleTableSlot,
|
|
* if no more tuples are available.
|
|
* ----------------
|
|
*/
|
|
typedef TupleTableSlot *(*ExecProcNodeMtd)(struct PlanState *pstate);
|
|
|
|
/* ----------------
|
|
* PlanState node
|
|
*
|
|
* We never actually instantiate any PlanState nodes; this is just the common
|
|
* abstract superclass for all PlanState-type nodes.
|
|
* ----------------
|
|
*/
|
|
typedef struct PlanState {
|
|
NodeTag type;
|
|
|
|
Plan* plan; /* associated Plan node */
|
|
|
|
EState* state; /* at execution time, states of individual
|
|
* nodes point to one EState for the whole
|
|
* top-level plan */
|
|
|
|
ExecProcNodeMtd ExecProcNode; /* function to return next tuple */
|
|
ExecProcNodeMtd ExecProcNodeReal; /* actual function, if above is a
|
|
* wrapper */
|
|
|
|
Instrumentation* instrument; /* Optional runtime stats for this node */
|
|
|
|
MemoryContext nodeContext; /* Memory Context for this Node (only if enable_memory_limit) */
|
|
|
|
/*
|
|
* Common structural data for all Plan types. These links to subsidiary
|
|
* state trees parallel links in the associated plan tree (except for the
|
|
* subPlan list, which does not exist in the plan tree).
|
|
*/
|
|
List* qual; /* implicitly-ANDed qual conditions */
|
|
struct PlanState* lefttree; /* input plan tree(s) */
|
|
struct PlanState* righttree;
|
|
List* initPlan; /* Init SubPlanState nodes (un-correlated expr subselects) */
|
|
List* subPlan; /* SubPlanState nodes in my expressions */
|
|
|
|
/*
|
|
* State for management of parameter-change-driven rescanning
|
|
*/
|
|
Bitmapset* chgParam; /* set of IDs of changed Params */
|
|
|
|
/*
|
|
* Other run-time state needed by most if not all node types.
|
|
*/
|
|
TupleTableSlot* ps_ResultTupleSlot; /* slot for my result tuples */
|
|
ExprContext* ps_ExprContext; /* node's expression-evaluation context */
|
|
ProjectionInfo* ps_ProjInfo; /* info for doing tuple projection */
|
|
|
|
int64 ps_rownum; /* store current rownum */
|
|
List* targetlist; /* target list to be computed at this node */
|
|
HbktScanSlot hbktScanSlot;
|
|
bool vectorized; // is vectorized?
|
|
|
|
bool earlyFreed; /* node memory already freed? */
|
|
uint8 stubType; /* node stub execution type, see @PlanStubType */
|
|
bool recursive_reset; /* node already reset? */
|
|
bool qual_is_inited;
|
|
|
|
bool do_not_reset_rownum;
|
|
bool ps_vec_TupFromTlist; /* state flag for processing set-valued functions in targetlist */
|
|
vectarget_func jitted_vectarget; /* LLVM IR function pointer to point to the codegened targetlist expr. */
|
|
|
|
/*
|
|
* Describe issues found in curernt plan node, mainly used for issue de-duplication
|
|
* of data skew and inaccurate e-rows
|
|
*/
|
|
List* plan_issues;
|
|
} PlanState;
|
|
|
|
static inline bool planstate_need_stub(PlanState* ps)
|
|
{
|
|
return ps->stubType != PST_None;
|
|
}
|
|
|
|
/* ----------------
|
|
* these are defined to avoid confusion problems with "left"
|
|
* and "right" and "inner" and "outer". The convention is that
|
|
* the "left" plan is the "outer" plan and the "right" plan is
|
|
* the inner plan, but these make the code more readable.
|
|
* ----------------
|
|
*/
|
|
#define innerPlanState(node) (((PlanState*)(node))->righttree)
|
|
#define outerPlanState(node) (((PlanState*)(node))->lefttree)
|
|
|
|
/* Macros for inline access to certain instrumentation counters */
|
|
#define InstrCountFiltered1(node, delta) \
|
|
do { \
|
|
if (((PlanState*)(node))->instrument) \
|
|
((PlanState*)(node))->instrument->nfiltered1 += (delta); \
|
|
} while (0)
|
|
#define InstrCountFiltered2(node, delta) \
|
|
do { \
|
|
if (((PlanState*)(node))->instrument) \
|
|
((PlanState*)(node))->instrument->nfiltered2 += (delta); \
|
|
} while (0)
|
|
|
|
/*
|
|
* EPQState is state for executing an EvalPlanQual recheck on a candidate
|
|
* tuple in ModifyTable or LockRows. The estate and planstate fields are
|
|
* NULL if inactive.
|
|
*/
|
|
typedef struct EPQState {
|
|
EState* estate; /* subsidiary EState */
|
|
PlanState* planstate; /* plan state tree ready to be executed */
|
|
TupleTableSlot* origslot; /* original output tuple to be rechecked */
|
|
Plan* plan; /* plan tree to be executed */
|
|
List* arowMarks; /* ExecAuxRowMarks (non-locking only) */
|
|
int epqParam; /* ID of Param to force scan node re-eval */
|
|
/*
|
|
* We need its memory context to palloc es_epqTupleSlot if needed
|
|
*/
|
|
EState *parentestate;
|
|
ProjectionInfo** projInfos; /* for multiple modifying to fetch slot. */
|
|
} EPQState;
|
|
|
|
/* ----------------
|
|
* ResultState information
|
|
* ----------------
|
|
*/
|
|
typedef struct ResultState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
ExprState* resconstantqual;
|
|
bool rs_done; /* are we done? */
|
|
bool rs_checkqual; /* do we need to check the qual? */
|
|
} ResultState;
|
|
|
|
/* ----------------
|
|
* MergeActionState information
|
|
* ----------------
|
|
*/
|
|
typedef struct MergeActionState {
|
|
NodeTag type;
|
|
bool matched; /* true=MATCHED, false=NOT MATCHED */
|
|
ExprState* whenqual; /* WHEN AND conditions */
|
|
CmdType commandType; /* INSERT/UPDATE/DELETE/DO NOTHING */
|
|
ProjectionInfo* proj; /* tuple projection info */
|
|
TupleDesc tupDesc; /* tuple descriptor for projection */
|
|
JunkFilter* junkfilter; /* junkfilter for UPDATE */
|
|
VectorBatch* scanBatch; /* scan batch for UPDATE */
|
|
} MergeActionState;
|
|
|
|
/* ----------------
|
|
* UpsertState information
|
|
* ----------------
|
|
*/
|
|
typedef struct UpsertState
|
|
{
|
|
NodeTag type;
|
|
UpsertAction us_action; /* Flags showing DUPLICATE UPDATE NOTHING or SOMETHING */
|
|
TupleTableSlot *us_existing; /* slot to store existing target tuple in */
|
|
List *us_excludedtlist; /* the excluded pseudo relation's tlist */
|
|
TupleTableSlot *us_updateproj; /* slot to update */
|
|
List *us_updateWhere; /* state for the upsert where clause */
|
|
} UpsertState;
|
|
|
|
/* ----------------
|
|
* ProjectSetState information
|
|
* ----------------
|
|
*/
|
|
typedef struct ProjectSetState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
Node **elems; /* array of expression states */
|
|
ExprDoneCond *elemdone; /* array of per-SRF is-done states */
|
|
int nelems; /* length of elemdone[] array */
|
|
bool pending_srf_tuples; /* still evaluating srfs in tlist? */
|
|
MemoryContext argcontext; /* context for SRF arguments */
|
|
} ProjectSetState;
|
|
|
|
/* ----------------
|
|
* ModifyTableState information
|
|
* ----------------
|
|
*/
|
|
typedef struct ModifyTableState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
CmdType operation; /* INSERT, UPDATE, or DELETE */
|
|
bool canSetTag; /* do we set the command tag/es_processed? */
|
|
bool mt_done; /* are we done? */
|
|
bool isReplace;
|
|
bool isConflict;
|
|
bool isinherit;
|
|
PlanState** mt_plans; /* subplans (one per target rel) */
|
|
#ifdef PGXC
|
|
PlanState** mt_remoterels; /* per-target remote query node */
|
|
PlanState** mt_insert_remoterels; /* per-target remote query node */
|
|
PlanState** mt_update_remoterels; /* per-target remote query node */
|
|
PlanState** mt_delete_remoterels; /* per-target remote query node */
|
|
#endif
|
|
int mt_nplans; /* number of plans in the array */
|
|
int mt_whichplan; /* which one is being executed (0..n-1) */
|
|
ResultRelInfo* resultRelInfo; /* per-subplan target relations */
|
|
List** mt_arowmarks; /* per-subplan ExecAuxRowMark lists */
|
|
EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
|
|
bool fireBSTriggers; /* do we need to fire stmt triggers? */
|
|
Relation delete_delta_rel; /* for online expansion's delete data catchup */
|
|
|
|
// For error table
|
|
//
|
|
Relation errorRel;
|
|
ErrorCacheEntry* cacheEnt;
|
|
|
|
TupleTableSlot* mt_scan_slot;
|
|
TupleTableSlot* mt_update_constr_slot; /* slot to store target tuple in for checking constraints */
|
|
TupleTableSlot* mt_insert_constr_slot; /* slot to store target tuple in for checking constraints */
|
|
TupleTableSlot* mt_mergeproj; /* MERGE action projection target */
|
|
uint32 mt_merge_subcommands; /* Flags showing which subcommands are present INS/UPD/DEL/DO NOTHING */
|
|
UpsertState* mt_upsert; /* DUPLICATE KEY UPDATE evaluation state */
|
|
instr_time first_tuple_modified; /* record the end time for the first tuple inserted, deleted, or updated */
|
|
ExprContext* limitExprContext; /* for limit expresssion */
|
|
|
|
List* targetlists; /* for multiple modifying, targetlist's list for each result relation. */
|
|
List* mt_ResultTupleSlots; /* for multiple modifying, ResultTupleSlot list for build mt_ProjInfos. */
|
|
ProjectionInfo** mt_ProjInfos; /* for multiple modifying, projectInfo list array for each result relation. */
|
|
char** partExprKeyStrArray; /* for multiple modifying, partition expr key */
|
|
#ifdef USE_SPQ
|
|
bool* mt_isSplitUpdates; /* per-subplan flag to indicate if it's a split update */
|
|
#endif
|
|
} ModifyTableState;
|
|
|
|
typedef struct CopyFromManagerData* CopyFromManager;
|
|
|
|
typedef struct DistInsertSelectState {
|
|
ModifyTableState mt;
|
|
int rows;
|
|
MemoryContext insert_mcxt;
|
|
CopyFromManager mgr;
|
|
BulkInsertState bistate;
|
|
PageCompress* pcState;
|
|
} DistInsertSelectState;
|
|
|
|
/* ----------------
|
|
* AppendState information
|
|
*
|
|
* nplans how many plans are in the array
|
|
* whichplan which plan is being executed (0 .. n-1)
|
|
* ----------------
|
|
*/
|
|
typedef struct AppendState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
PlanState** appendplans; /* array of PlanStates for my inputs */
|
|
int as_nplans;
|
|
int as_whichplan;
|
|
} AppendState;
|
|
|
|
/* ----------------
|
|
* MergeAppendState information
|
|
*
|
|
* nplans how many plans are in the array
|
|
* nkeys number of sort key columns
|
|
* sortkeys sort keys in SortSupport representation
|
|
* slots current output tuple of each subplan
|
|
* heap heap of active tuples (represented as array indexes)
|
|
* heap_size number of active heap entries
|
|
* initialized true if we have fetched first tuple from each subplan
|
|
* last_slot last subplan fetched from (which must be re-called)
|
|
* ----------------
|
|
*/
|
|
typedef struct MergeAppendState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
PlanState** mergeplans; /* array of PlanStates for my inputs */
|
|
int ms_nplans;
|
|
int ms_nkeys;
|
|
SortSupport ms_sortkeys; /* array of length ms_nkeys */
|
|
TupleTableSlot** ms_slots; /* array of length ms_nplans */
|
|
int* ms_heap; /* array of length ms_nplans */
|
|
int ms_heap_size; /* current active length of ms_heap[] */
|
|
bool ms_initialized; /* are subplans started? */
|
|
int ms_last_slot; /* last subplan slot we returned from */
|
|
} MergeAppendState;
|
|
|
|
/* ----------------
|
|
* RecursiveUnionState information
|
|
*
|
|
* RecursiveUnionState is used for performing a recursive union.
|
|
*
|
|
* recursing T when we're done scanning the non-recursive term
|
|
* intermediate_empty T if intermediate_table is currently empty
|
|
* working_table working table (to be scanned by recursive term)
|
|
* intermediate_table current recursive output (next generation of WT)
|
|
* ----------------
|
|
*/
|
|
struct StartWithOpState;
|
|
struct RecursiveUnionController;
|
|
typedef struct RecursiveUnionState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
bool recursing;
|
|
bool intermediate_empty;
|
|
Tuplestorestate* working_table;
|
|
Tuplestorestate* intermediate_table;
|
|
int iteration;
|
|
/* Remaining fields are unused in UNION ALL case */
|
|
FmgrInfo* eqfunctions; /* per-grouping-field equality fns */
|
|
FmgrInfo* hashfunctions; /* per-grouping-field hash fns */
|
|
MemoryContext tempContext; /* short-term context for comparisons */
|
|
TupleHashTable hashtable; /* hash table for tuples already seen */
|
|
MemoryContext tableContext; /* memory context containing hash table */
|
|
MemoryContext convertContext; /* memory context for start with convert tuple */
|
|
|
|
/*
|
|
* MPP with-recursive support
|
|
*/
|
|
/* Distributed with-recursive execution controller for current RecursiveUnion operator */
|
|
RecursiveUnionController* rucontroller;
|
|
|
|
/* record the number of tuples that produced by current iteration step */
|
|
uint64 step_tuple_produced;
|
|
|
|
/*
|
|
* The share memory context pointer that is used in distributed recursive CTE
|
|
* processing where WorkTable is access via different stream threads, we need
|
|
* put it on higher level of memory context to persists the whole query runing
|
|
* stage.
|
|
*/
|
|
MemoryContext shareContext;
|
|
|
|
/* support start with*/
|
|
StartWithOpState *swstate;
|
|
|
|
/*
|
|
* tuple's index of relative order position in current iteration level
|
|
* only useful once start with...connect by..siblings all exist.
|
|
*/
|
|
uint64 sw_tuple_idx;
|
|
} RecursiveUnionState;
|
|
|
|
/* ----------------
|
|
* StartWithOpState information
|
|
* ----------------
|
|
*/
|
|
#define PSEUDO_COLUMN_NUM 4
|
|
typedef struct StartWithOpState
|
|
{
|
|
PlanState ps;
|
|
|
|
/* other attributes */
|
|
int swop_status;
|
|
/*
|
|
* An array of TargetEntry reference to store the entry for start-with pseudo
|
|
* return columns's TLE
|
|
* - entry[0] LEVEL
|
|
* - entry[1] CONNECT_BY_ISLEAF
|
|
* - entry[2] CONNECT_BY_ISCYCLE
|
|
* - entry[3] ROWNUM
|
|
*/
|
|
TargetEntry *sw_pseudoCols[PSEUDO_COLUMN_NUM];
|
|
|
|
IterationStats iterStats;
|
|
|
|
/* variables to help calculate pseodu return columns */
|
|
TupleTableSlot *sw_workingSlot; /* A dedicate slot to hold tuple-2-tuple
|
|
conversion in side of StartWithOp node,
|
|
basically do not share use result tuple
|
|
to to avoid to tuple store,fetch,
|
|
conversion mess up */
|
|
Tuplestorestate *sw_workingTable; /* Hold incoming tuple slto from RU and processed
|
|
one-by-on and store into resultTable */
|
|
|
|
Tuplestorestate *sw_backupTable; /* Hold a copy of sw_workingTable*/
|
|
|
|
Tuplestorestate *sw_resultTable; /* final calculated result stored int */
|
|
|
|
AttrNumber sw_keyAttnum;
|
|
const char *sw_curKeyArrayStr;
|
|
|
|
/* tuple slot value array for conversion (to avoid per-tupe process memory alloc/free) */
|
|
Datum *sw_values;
|
|
bool *sw_isnull;
|
|
int sw_connect_by_level;
|
|
uint64 sw_rownum;
|
|
int sw_level;
|
|
int sw_numtuples; /* number of tuples in current level */
|
|
|
|
MemoryContext sw_context;
|
|
List* sw_cycle_rowmarks;
|
|
List* sw_leaf_rowmarks;
|
|
} StartWithOpState;
|
|
|
|
/* ----------------
|
|
* BitmapAndState information
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapAndState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
PlanState** bitmapplans; /* array of PlanStates for my inputs */
|
|
int nplans; /* number of input plans */
|
|
} BitmapAndState;
|
|
|
|
/* ----------------
|
|
* BitmapOrState information
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapOrState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
PlanState** bitmapplans; /* array of PlanStates for my inputs */
|
|
int nplans; /* number of input plans */
|
|
} BitmapOrState;
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Run time predicate information
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
typedef struct RunTimeParamPredicateInfo {
|
|
ExprState* paraExecExpr; /* internal executor parameter predicate information. */
|
|
Expr* opExpr; /* the operator expression */
|
|
AttrNumber varNoPos; /* an order number in the hdfsScanPredicateArr. */
|
|
int32 typeMod; /* var typmode. */
|
|
Oid datumType; /* the parameter data type. */
|
|
Oid varTypeOid; /* var type oid. */
|
|
int32 paramPosition; /* the parameter predicate position in *hdfsScanPredicateArr. */
|
|
} RunTimeParamPredicateInfo;
|
|
|
|
/* ----------------
|
|
* SampleScanInfo information
|
|
* ----------------
|
|
*/
|
|
typedef struct SampleScanParams {
|
|
List* args; /* expr states for TABLESAMPLE params */
|
|
ExprState* repeatable; /* expr state for REPEATABLE expr */
|
|
TableSampleType sampleType; /* sample scan type.*/
|
|
/* use struct pointer to avoid including tsmapi.h here */
|
|
void* tsm_state; /* tablesample method can keep state here */
|
|
} SampleScanParams;
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Batch Scan Information
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
struct ScanBatchResult {
|
|
int rows; /* rows number for current page. */
|
|
TupleTableSlot** scanTupleSlotInBatch; /* array size of BatchMaxSize, stores tuples scanned in a page */
|
|
};
|
|
|
|
struct ScanBatchColAttr {
|
|
int colId; /* only save the used cols. */
|
|
bool lateRead; /* for project */
|
|
bool isProject; /* is project? */
|
|
};
|
|
|
|
struct ScanBatchState {
|
|
VectorBatch* pScanBatch; /* batch formed from tuples */
|
|
int scanTupleSlotMaxNum; /* max row number of tuples can be scanned once */
|
|
int colNum;
|
|
int maxcolId;
|
|
ScanBatchColAttr* colAttr; /* for qual and project, save attributes. */
|
|
bool *nullflag; /*indicate the batch has null value for performance */
|
|
bool scanfinished; /* last time return with rows, but pages of this partition is read out */
|
|
ScanBatchResult scanBatch;
|
|
};
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Scan State Information
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
|
|
/* ----------------
|
|
* ScanState information
|
|
*
|
|
* ScanState extends PlanState for node types that represent
|
|
* scans of an underlying relation. It can also be used for nodes
|
|
* that scan the output of an underlying plan node --- in that case,
|
|
* only ScanTupleSlot is actually useful, and it refers to the tuple
|
|
* retrieved from the subplan.
|
|
*
|
|
* currentRelation relation being scanned (NULL if none)
|
|
* currentScanDesc current scan descriptor for scan (NULL if none)
|
|
* ScanTupleSlot pointer to slot in tuple table holding scan tuple
|
|
* ----------------
|
|
*/
|
|
struct ScanState;
|
|
struct SeqScanAccessor;
|
|
|
|
/*
|
|
* prototypes from functions in execScan.c
|
|
*/
|
|
typedef TupleTableSlot *(*ExecScanAccessMtd) (ScanState *node);
|
|
typedef bool(*ExecScanRecheckMtd) (ScanState *node, TupleTableSlot *slot);
|
|
typedef void (*SeqScanGetNextMtd)(TableScanDesc scan, TupleTableSlot* slot, ScanDirection direction,
|
|
bool* has_cur_xact_write);
|
|
|
|
typedef struct ScanState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
Relation ss_currentRelation;
|
|
TableScanDesc ss_currentScanDesc;
|
|
TupleTableSlot* ss_ScanTupleSlot;
|
|
|
|
SeqScanGetNextMtd fillNextSlotFunc;
|
|
ExecScanAccessMtd ScanNextMtd;
|
|
|
|
bool scanBatchMode;
|
|
bool ss_ReScan;
|
|
bool isPartTbl;
|
|
bool isSampleScan; /* identify is it table sample scan or not. */
|
|
bool runTimePredicatesReady;
|
|
bool is_scan_end; /* @hdfs Mark whether iterator is over or not, if the scan uses informational constraint. */
|
|
bool isVersionScan;
|
|
|
|
int currentSlot; /* current iteration position */
|
|
int part_id;
|
|
int startPartitionId; /* start partition id for parallel threads. */
|
|
int endPartitionId; /* end partition id for parallel threads. */
|
|
|
|
LOCKMODE lockMode;
|
|
ScanDirection partScanDirection;
|
|
|
|
Relation ss_currentPartition;
|
|
List* partitions; /* list of Partition */
|
|
List* subpartitions; /* list of SubPartition */
|
|
List* runTimeParamPredicates;
|
|
SeqScanAccessor* ss_scanaccessor; /* prefetch related */
|
|
List* subPartLengthList;
|
|
RangeScanInRedis rangeScanInRedis; /* if it is a range scan in redistribution time */
|
|
SampleScanParams sampleScanInfo; /* TABLESAMPLE params include type/seed/repeatable. */
|
|
ScanBatchState* scanBatchState;
|
|
Snapshot timecapsuleSnapshot; /* timecapusule snap info */
|
|
} ScanState;
|
|
|
|
/*
|
|
* SeqScan uses a bare ScanState as its state node, since it needs
|
|
* no additional fields.
|
|
*/
|
|
typedef ScanState SeqScanState;
|
|
|
|
#ifdef USE_SPQ
|
|
/*
|
|
* SpqSeqScanState
|
|
*/
|
|
typedef struct SpqSeqScanState {
|
|
SeqScanState ss;
|
|
void* pageManager;
|
|
void* blockManager;
|
|
} SpqSeqScanState;
|
|
typedef struct AssertOpState {
|
|
PlanState ps;
|
|
} AssertOpState;
|
|
|
|
/* ----------------
|
|
* State of each scanner of the ShareInput node
|
|
* ----------------
|
|
*/
|
|
typedef struct ShareInputScanState {
|
|
ScanState ss;
|
|
Tuplestorestate *ts_state;
|
|
int ts_pos;
|
|
struct shareinput_local_state *local_state;
|
|
struct shareinput_Xslice_reference *ref;
|
|
bool isready;
|
|
} ShareInputScanState;
|
|
|
|
typedef struct SequenceState {
|
|
PlanState ps;
|
|
PlanState **subplans;
|
|
int numSubplans;
|
|
|
|
/*
|
|
* True if no subplan has been executed.
|
|
*/
|
|
bool initState;
|
|
} SequenceState;
|
|
|
|
/*
|
|
* ExecNode for Split.
|
|
* This operator contains a Plannode in PlanState.
|
|
* The Plannode contains indexes to the ctid, insert, delete, resjunk columns
|
|
* needed for adding the action (Insert/Delete).
|
|
* A MemoryContext and TupleTableSlot are maintained to keep the INSERT
|
|
* tuple until requested.
|
|
*/
|
|
typedef struct SplitUpdateState {
|
|
PlanState ps;
|
|
bool processInsert; /* flag that specifies the operator's next action. */
|
|
TupleTableSlot *insertTuple; /* tuple to Insert */
|
|
TupleTableSlot *deleteTuple; /* tuple to Delete */
|
|
} SplitUpdateState;
|
|
#endif
|
|
/*
|
|
* These structs store information about index quals that don't have simple
|
|
* constant right-hand sides. See comments for ExecIndexBuildScanKeys()
|
|
* for discussion.
|
|
*/
|
|
typedef struct {
|
|
ScanKey scan_key; /* scankey to put value into */
|
|
ExprState* key_expr; /* expr to evaluate to get value */
|
|
bool key_toastable; /* is expr's result a toastable datatype? */
|
|
} IndexRuntimeKeyInfo;
|
|
|
|
typedef struct {
|
|
ScanKey scan_key; /* scankey to put value into */
|
|
ExprState* array_expr; /* expr to evaluate to get array value */
|
|
int next_elem; /* next array element to use */
|
|
int num_elems; /* number of elems in current array value */
|
|
Datum* elem_values; /* array of num_elems Datums */
|
|
bool* elem_nulls; /* array of num_elems is-null flags */
|
|
} IndexArrayKeyInfo;
|
|
|
|
/* ----------------
|
|
* IndexScanState information
|
|
*
|
|
* indexqualorig execution state for indexqualorig expressions
|
|
* ScanKeys Skey structures for index quals
|
|
* NumScanKeys number of ScanKeys
|
|
* OrderByKeys Skey structures for index ordering operators
|
|
* NumOrderByKeys number of OrderByKeys
|
|
* RuntimeKeys info about Skeys that must be evaluated at runtime
|
|
* NumRuntimeKeys number of RuntimeKeys
|
|
* RuntimeKeysReady true if runtime Skeys have been computed
|
|
* RuntimeContext expr context for evaling runtime Skeys
|
|
* RelationDesc index relation descriptor
|
|
* ScanDesc index scan descriptor
|
|
* ----------------
|
|
*/
|
|
typedef struct IndexScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
List* indexqualorig;
|
|
ScanKey iss_ScanKeys;
|
|
int iss_NumScanKeys;
|
|
ScanKey iss_OrderByKeys;
|
|
int iss_NumOrderByKeys;
|
|
IndexRuntimeKeyInfo* iss_RuntimeKeys;
|
|
int iss_NumRuntimeKeys;
|
|
bool iss_RuntimeKeysReady;
|
|
ExprContext* iss_RuntimeContext;
|
|
Relation iss_RelationDesc;
|
|
IndexScanDesc iss_ScanDesc;
|
|
List* iss_IndexPartitionList;
|
|
LOCKMODE lockMode;
|
|
Relation iss_CurrentIndexPartition;
|
|
} IndexScanState;
|
|
|
|
/* ----------------
|
|
* IndexOnlyScanState information
|
|
*
|
|
* indexqual execution state for indexqual expressions
|
|
* ScanKeys Skey structures for index quals
|
|
* NumScanKeys number of ScanKeys
|
|
* OrderByKeys Skey structures for index ordering operators
|
|
* NumOrderByKeys number of OrderByKeys
|
|
* RuntimeKeys info about Skeys that must be evaluated at runtime
|
|
* NumRuntimeKeys number of RuntimeKeys
|
|
* RuntimeKeysReady true if runtime Skeys have been computed
|
|
* RuntimeContext expr context for evaling runtime Skeys
|
|
* RelationDesc index relation descriptor
|
|
* ScanDesc index scan descriptor
|
|
* VMBuffer buffer in use for visibility map testing, if any
|
|
* HeapFetches number of tuples we were forced to fetch from heap
|
|
* ----------------
|
|
*/
|
|
typedef struct IndexOnlyScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
List* indexqual;
|
|
ScanKey ioss_ScanKeys;
|
|
int ioss_NumScanKeys;
|
|
ScanKey ioss_OrderByKeys;
|
|
int ioss_NumOrderByKeys;
|
|
IndexRuntimeKeyInfo* ioss_RuntimeKeys;
|
|
int ioss_NumRuntimeKeys;
|
|
bool ioss_RuntimeKeysReady;
|
|
ExprContext* ioss_RuntimeContext;
|
|
Relation ioss_RelationDesc;
|
|
IndexScanDesc ioss_ScanDesc;
|
|
Buffer ioss_VMBuffer;
|
|
long ioss_HeapFetches;
|
|
List* ioss_IndexPartitionList;
|
|
LOCKMODE lockMode;
|
|
Relation ioss_CurrentIndexPartition;
|
|
} IndexOnlyScanState;
|
|
|
|
/* ----------------
|
|
* BitmapIndexScanState information
|
|
*
|
|
* result bitmap to return output into, or NULL
|
|
* ScanKeys Skey structures for index quals
|
|
* NumScanKeys number of ScanKeys
|
|
* RuntimeKeys info about Skeys that must be evaluated at runtime
|
|
* NumRuntimeKeys number of RuntimeKeys
|
|
* ArrayKeys info about Skeys that come from ScalarArrayOpExprs
|
|
* NumArrayKeys number of ArrayKeys
|
|
* RuntimeKeysReady true if runtime Skeys have been computed
|
|
* RuntimeContext expr context for evaling runtime Skeys
|
|
* RelationDesc index relation descriptor
|
|
* ScanDesc index scan descriptor
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapIndexScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
TIDBitmap* biss_result;
|
|
ScanKey biss_ScanKeys;
|
|
int biss_NumScanKeys;
|
|
IndexRuntimeKeyInfo* biss_RuntimeKeys;
|
|
int biss_NumRuntimeKeys;
|
|
IndexArrayKeyInfo* biss_ArrayKeys;
|
|
int biss_NumArrayKeys;
|
|
bool biss_RuntimeKeysReady;
|
|
ExprContext* biss_RuntimeContext;
|
|
Relation biss_RelationDesc;
|
|
IndexScanDesc biss_ScanDesc;
|
|
List* biss_IndexPartitionList;
|
|
LOCKMODE lockMode;
|
|
Relation biss_CurrentIndexPartition;
|
|
} BitmapIndexScanState;
|
|
|
|
/* ----------------
|
|
* BitmapHeapScanState information
|
|
*
|
|
* bitmapqualorig execution state for bitmapqualorig expressions
|
|
* tbm bitmap obtained from child index scan(s)
|
|
* tbmiterator iterator for scanning current pages
|
|
* tbmres current-page data
|
|
* prefetch_iterator iterator for prefetching ahead of current page
|
|
* prefetch_pages # pages prefetch iterator is ahead of current
|
|
* prefetch_target target prefetch distance
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapHeapScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
List* bitmapqualorig;
|
|
TIDBitmap* tbm;
|
|
TBMIterator* tbmiterator;
|
|
TBMIterateResult* tbmres;
|
|
long exact_pages;
|
|
long lossy_pages;
|
|
TBMIterator* prefetch_iterator;
|
|
int prefetch_pages;
|
|
int prefetch_target;
|
|
GPIScanDesc gpi_scan; /* global partition index scan use information */
|
|
CBIScanDesc cbi_scan; /* for crossbucket index scan */
|
|
} BitmapHeapScanState;
|
|
|
|
/* ----------------
|
|
* TidScanState information
|
|
*
|
|
* isCurrentOf scan has a CurrentOfExpr qual
|
|
* NumTids number of tids in this scan
|
|
* TidPtr index of currently fetched tid
|
|
* TidList evaluated item pointers (array of size NumTids)
|
|
* ----------------
|
|
*/
|
|
typedef struct TidScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
List* tss_tidexprs;
|
|
bool tss_isCurrentOf;
|
|
Relation tss_CurrentOf_CurrentPartition;
|
|
int tss_NumTids;
|
|
int tss_TidPtr;
|
|
int tss_MarkTidPtr;
|
|
ItemPointerData* tss_TidList;
|
|
union {
|
|
HeapTupleData tss_htup;
|
|
UHeapTupleData tss_uhtup;
|
|
};
|
|
/* put decompressed tuple data into tss_ctbuf_hdr be careful , when malloc memory should give extra mem for
|
|
*xs_ctbuf_hdr. t_bits which is varlength arr */
|
|
HeapTupleHeaderData tss_ctbuf_hdr;
|
|
} TidScanState;
|
|
|
|
#define SizeofTidScanState (offsetof(TidScanState, tss_ctbuf_hdr) + SizeofHeapTupleHeader)
|
|
|
|
/* ----------------
|
|
* SubqueryScanState information
|
|
*
|
|
* SubqueryScanState is used for scanning a sub-query in the range table.
|
|
* ScanTupleSlot references the current output tuple of the sub-query.
|
|
* ----------------
|
|
*/
|
|
typedef struct SubqueryScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
PlanState* subplan;
|
|
} SubqueryScanState;
|
|
|
|
/* ----------------
|
|
* FunctionScanState information
|
|
*
|
|
* Function nodes are used to scan the results of a
|
|
* function appearing in FROM (typically a function returning set).
|
|
*
|
|
* eflags node's capability flags
|
|
* tupdesc expected return tuple description
|
|
* tuplestorestate private state of tuplestore.c
|
|
* funcexpr state for function expression being evaluated
|
|
* ----------------
|
|
*/
|
|
typedef struct FunctionScanState {
|
|
ScanState ss; /* Its first field is NodeTag */
|
|
int eflags;
|
|
TupleDesc tupdesc;
|
|
Tuplestorestate* tuplestorestate;
|
|
ExprState* funcexpr;
|
|
bool atomic; /* Atomic execution context, does not allow transactions */
|
|
} FunctionScanState;
|
|
|
|
/* ----------------
|
|
* ValuesScanState information
|
|
*
|
|
* ValuesScan nodes are used to scan the results of a VALUES list
|
|
*
|
|
* rowcontext per-expression-list context
|
|
* exprlists array of expression lists being evaluated
|
|
* exprstatelists array of expression state lists, for subplans only
|
|
* array_len size of above array
|
|
* curr_idx current array index (0-based)
|
|
* marked_idx marked position (for mark/restore)
|
|
*
|
|
* Note: ss.ps.ps_ExprContext is used to evaluate any qual or projection
|
|
* expressions attached to the node. We create a second ExprContext,
|
|
* rowcontext, in which to build the executor expression state for each
|
|
* Values sublist. Resetting this context lets us get rid of expression
|
|
* state for each row, avoiding major memory leakage over a long values list.
|
|
* However, that doesn't work for sublists containing SubPlans, because a
|
|
* SubPlan has to be connected up to the outer plan tree to work properly.
|
|
* Therefore, for only those sublists containing SubPlans, we do expression
|
|
* state construction at executor start, and store those pointers in
|
|
* exprstatelists[]. NULL entries in that array correspond to simple
|
|
* subexpressions that are handled as described above.
|
|
* ----------------
|
|
*/
|
|
typedef struct ValuesScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
ExprContext* rowcontext;
|
|
List** exprlists;
|
|
List** exprstatelists; /* array of expression state lists, for subplans only */
|
|
int array_len; /* size of above array */
|
|
int curr_idx;
|
|
int marked_idx;
|
|
} ValuesScanState;
|
|
|
|
/* ----------------
|
|
* CteScanState information
|
|
*
|
|
* CteScan nodes are used to scan a CommonTableExpr query.
|
|
*
|
|
* Multiple CteScan nodes can read out from the same CTE query. We use
|
|
* a tuplestore to hold rows that have been read from the CTE query but
|
|
* not yet consumed by all readers.
|
|
* ----------------
|
|
*/
|
|
typedef struct CteScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
int eflags; /* capability flags to pass to tuplestore */
|
|
int readptr; /* index of my tuplestore read pointer */
|
|
PlanState* cteplanstate; /* PlanState for the CTE query itself */
|
|
/* Link to the "leader" CteScanState (possibly this same node) */
|
|
struct CteScanState* leader;
|
|
/* The remaining fields are only valid in the "leader" CteScanState */
|
|
Tuplestorestate* cte_table; /* rows already read from the CTE query */
|
|
bool eof_cte; /* reached end of CTE query? */
|
|
} CteScanState;
|
|
|
|
/* ----------------
|
|
* WorkTableScanState information
|
|
*
|
|
* WorkTableScan nodes are used to scan the work table created by
|
|
* a RecursiveUnion node. We locate the RecursiveUnion node
|
|
* during executor startup.
|
|
* ----------------
|
|
*/
|
|
typedef struct WorkTableScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
RecursiveUnionState* rustate;
|
|
} WorkTableScanState;
|
|
|
|
/* ----------------
|
|
* ForeignScanState information
|
|
*
|
|
* ForeignScan nodes are used to scan foreign-data tables.
|
|
* ----------------
|
|
*/
|
|
typedef struct ForeignScanState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
ExprState* fdw_recheck_quals; /* original quals not in ss.ps.qual */
|
|
/* use struct pointer to avoid including fdwapi.h here */
|
|
struct FdwRoutine* fdwroutine;
|
|
void* fdw_state; /* foreign-data wrapper can keep state here */
|
|
|
|
MemoryContext scanMcxt;
|
|
|
|
ForeignOptions* options;
|
|
} ForeignScanState;
|
|
|
|
/* ----------------
|
|
* ExtensiblePlanState information
|
|
*
|
|
* ExtensiblePlan nodes are used to execute extensible code within executor.
|
|
*
|
|
* Core code must avoid assuming that the ExtensiblePlanState is only as large as
|
|
* the structure declared here; providers are allowed to make it the first
|
|
* element in a larger structure, and typically would need to do so. The
|
|
* struct is actually allocated by the CreateExtensiblePlanState method associated
|
|
* with the plan node. Any additional fields can be initialized there, or in
|
|
* the BeginExtensiblePlan method.
|
|
* ----------------
|
|
*/
|
|
struct ExplainState; /* avoid including explain.h here */
|
|
struct ExtensiblePlanState;
|
|
|
|
typedef struct ExtensibleExecMethods {
|
|
const char* ExtensibleName;
|
|
|
|
/* Executor methods: mark/restore are optional, the rest are required */
|
|
void (*BeginExtensiblePlan)(struct ExtensiblePlanState* node, EState* estate, int eflags);
|
|
TupleTableSlot* (*ExecExtensiblePlan)(struct ExtensiblePlanState* node);
|
|
void (*EndExtensiblePlan)(struct ExtensiblePlanState* node);
|
|
void (*ReScanExtensiblePlan)(struct ExtensiblePlanState* node);
|
|
void (*ExplainExtensiblePlan)(struct ExtensiblePlanState* node, List* ancestors, struct ExplainState* es);
|
|
} ExtensibleExecMethods;
|
|
|
|
typedef struct ExtensiblePlanState {
|
|
ScanState ss;
|
|
uint32 flags; /* mask of EXTENSIBLEPATH_* flags, see relation.h */
|
|
List* extensible_ps; /* list of child PlanState nodes, if any */
|
|
const ExtensibleExecMethods* methods;
|
|
} ExtensiblePlanState;
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Join State Information
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
|
|
/* ----------------
|
|
* JoinState information
|
|
*
|
|
* Superclass for state nodes of join plans.
|
|
* ----------------
|
|
*/
|
|
typedef struct JoinState {
|
|
PlanState ps;
|
|
JoinType jointype;
|
|
bool single_match;
|
|
List* joinqual; /* JOIN quals (in addition to ps.qual) */
|
|
List* nulleqqual;
|
|
} JoinState;
|
|
|
|
/* ----------------
|
|
* NestLoopState information
|
|
*
|
|
* NeedNewOuter true if need new outer tuple on next call
|
|
* MatchedOuter true if found a join match for current outer tuple
|
|
* NullInnerTupleSlot prepared null tuple for left outer joins
|
|
* ----------------
|
|
*/
|
|
typedef struct NestLoopState {
|
|
JoinState js; /* its first field is NodeTag */
|
|
bool nl_NeedNewOuter;
|
|
bool nl_MatchedOuter;
|
|
bool nl_MaterialAll;
|
|
TupleTableSlot* nl_NullInnerTupleSlot;
|
|
#ifdef USE_SPQ
|
|
List *nl_InnerJoinKeys; /* list of ExprState nodes */
|
|
List *nl_OuterJoinKeys; /* list of ExprState nodes */
|
|
bool nl_innerSideScanned; /* set to true once we've scanned all inner tuples the first time */
|
|
bool prefetch_inner;
|
|
#endif
|
|
} NestLoopState;
|
|
|
|
/* ----------------
|
|
* MergeJoinState information
|
|
*
|
|
* NumClauses number of mergejoinable join clauses
|
|
* Clauses info for each mergejoinable clause
|
|
* JoinState current state of ExecMergeJoin state machine
|
|
* SkipMarkRestore true if we may skip Mark and Restore operations
|
|
* ExtraMarks true to issue extra Mark operations on inner scan
|
|
* ConstFalseJoin true if we have a constant-false joinqual
|
|
* FillOuter true if should emit unjoined outer tuples anyway
|
|
* FillInner true if should emit unjoined inner tuples anyway
|
|
* MatchedOuter true if found a join match for current outer tuple
|
|
* MatchedInner true if found a join match for current inner tuple
|
|
* OuterTupleSlot slot in tuple table for cur outer tuple
|
|
* InnerTupleSlot slot in tuple table for cur inner tuple
|
|
* MarkedTupleSlot slot in tuple table for marked tuple
|
|
* NullOuterTupleSlot prepared null tuple for right outer joins
|
|
* NullInnerTupleSlot prepared null tuple for left outer joins
|
|
* OuterEContext workspace for computing outer tuple's join values
|
|
* InnerEContext workspace for computing inner tuple's join values
|
|
* ----------------
|
|
*/
|
|
/* private in nodeMergejoin.c: */
|
|
typedef struct MergeJoinClauseData* MergeJoinClause;
|
|
|
|
typedef struct MergeJoinState {
|
|
JoinState js; /* its first field is NodeTag */
|
|
int mj_NumClauses;
|
|
MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */
|
|
int mj_JoinState;
|
|
bool mj_SkipMarkRestore;
|
|
bool mj_ExtraMarks;
|
|
bool mj_ConstFalseJoin;
|
|
bool mj_FillOuter;
|
|
bool mj_FillInner;
|
|
bool mj_MatchedOuter;
|
|
bool mj_MatchedInner;
|
|
TupleTableSlot* mj_OuterTupleSlot;
|
|
TupleTableSlot* mj_InnerTupleSlot;
|
|
TupleTableSlot* mj_MarkedTupleSlot;
|
|
TupleTableSlot* mj_NullOuterTupleSlot;
|
|
TupleTableSlot* mj_NullInnerTupleSlot;
|
|
ExprContext* mj_OuterEContext;
|
|
ExprContext* mj_InnerEContext;
|
|
} MergeJoinState;
|
|
|
|
struct MergeJoinShared {
|
|
JoinState js; /* its first field is NodeTag */
|
|
int mj_NumClauses;
|
|
int mj_JoinState;
|
|
bool mj_ExtraMarks;
|
|
bool mj_ConstFalseJoin;
|
|
bool mj_FillOuter;
|
|
bool mj_FillInner;
|
|
bool mj_MatchedOuter;
|
|
bool mj_MatchedInner;
|
|
};
|
|
|
|
/* private in vecmergejoin.cpp: */
|
|
typedef struct VecMergeJoinClauseData* VecMergeJoinClause;
|
|
|
|
// Mark the offset of a row in a batch
|
|
// It is the same with integer and we rely on compiler to generate efficient
|
|
// code for structure copy.
|
|
struct MJBatchOffset {
|
|
// offset in the batch, starting from zero
|
|
uint16 m_offset;
|
|
|
|
// Flag: is it actually representing an empty row?
|
|
bool m_fEmpty;
|
|
// Flag: is the offset pointing to the marked batch?
|
|
bool m_fMarked;
|
|
// batch sequence: ok to wrap around
|
|
int m_batchSeq;
|
|
};
|
|
|
|
struct BatchAccessor {
|
|
// child query to retrieve data
|
|
PlanState* m_plan;
|
|
// Current offset. It also points to the batch the offset is against.
|
|
// The maxOffset is used to detect the end of the batch.
|
|
VectorBatch* m_curBatch;
|
|
int m_batchSeq;
|
|
int m_curOffset;
|
|
int m_maxOffset;
|
|
};
|
|
|
|
struct VecMergeJoinState : public MergeJoinShared {
|
|
// Vectorization run support
|
|
VecMergeJoinClause mj_Clauses;
|
|
MJBatchOffset mj_OuterOffset;
|
|
MJBatchOffset mj_InnerOffset;
|
|
ExprContext* mj_OuterEContext;
|
|
ExprContext* mj_InnerEContext;
|
|
// Marked batch and offset. We need both to represent a marked row.
|
|
MJBatchOffset mj_MarkedOffset;
|
|
VectorBatch* mj_MarkedBatch;
|
|
|
|
// Input batches (inner: 0, outer: 1). We record current progress on the
|
|
// input batches here.
|
|
BatchAccessor m_inputs[2];
|
|
|
|
// Previous batch join status. This is needed as some join types need
|
|
// to look backward to decide if we shall output current tuples.
|
|
MJBatchOffset m_prevInnerOffset;
|
|
bool m_prevInnerQualified;
|
|
MJBatchOffset m_prevOuterOffset;
|
|
bool m_prevOuterQualified;
|
|
|
|
// Result batch and intermediate results. pInner and pOuter hold the join
|
|
// candiates passed the join key checks.
|
|
bool m_fDone;
|
|
VectorBatch* m_pInnerMatch;
|
|
MJBatchOffset* m_pInnerOffset;
|
|
VectorBatch* m_pOuterMatch;
|
|
MJBatchOffset* m_pOuterOffset;
|
|
VectorBatch* m_pCurrentBatch;
|
|
VectorBatch* m_pReturnBatch;
|
|
vecqual_func jitted_joinqual; /* LLVM IR function pointer to point to codegened mj_joinqualexpr */
|
|
};
|
|
|
|
/* ----------------
|
|
* HashJoinState information
|
|
*
|
|
* hashclauses original form of the hashjoin condition
|
|
* hj_OuterHashKeys the outer hash keys in the hashjoin condition
|
|
* hj_InnerHashKeys the inner hash keys in the hashjoin condition
|
|
* hj_HashOperators the join operators in the hashjoin condition
|
|
* hj_HashTable hash table for the hashjoin
|
|
* (NULL if table not built yet)
|
|
* hj_CurHashValue hash value for current outer tuple
|
|
* hj_CurBucketNo regular bucket# for current outer tuple
|
|
* hj_CurSkewBucketNo skew bucket# for current outer tuple
|
|
* hj_CurTuple last inner tuple matched to current outer
|
|
* tuple, or NULL if starting search
|
|
* (hj_CurXXX variables are undefined if
|
|
* OuterTupleSlot is empty!)
|
|
* hj_OuterTupleSlot tuple slot for outer tuples
|
|
* hj_HashTupleSlot tuple slot for inner (hashed) tuples
|
|
* hj_NullOuterTupleSlot prepared null tuple for right/full outer joins
|
|
* hj_NullInnerTupleSlot prepared null tuple for left/full outer joins
|
|
* hj_FirstOuterTupleSlot first tuple retrieved from outer plan
|
|
* hj_JoinState current state of ExecHashJoin state machine
|
|
* hj_MatchedOuter true if found a join match for current outer
|
|
* hj_OuterNotEmpty true if outer relation known not empty
|
|
* ----------------
|
|
*/
|
|
/* these structs are defined in executor/hashjoin.h: */
|
|
typedef struct HashJoinTupleData* HashJoinTuple;
|
|
typedef struct HashJoinTableData* HashJoinTable;
|
|
|
|
typedef struct HashJoinState {
|
|
JoinState js; /* its first field is NodeTag */
|
|
List* hashclauses; /* list of ExprState nodes */
|
|
List* hj_OuterHashKeys; /* list of ExprState nodes */
|
|
List* hj_InnerHashKeys; /* list of ExprState nodes */
|
|
List* hj_HashOperators; /* list of operator OIDs */
|
|
HashJoinTable hj_HashTable;
|
|
uint32 hj_CurHashValue;
|
|
int hj_CurBucketNo;
|
|
int hj_CurSkewBucketNo;
|
|
HashJoinTuple hj_CurTuple;
|
|
/* pointer which follows hj_CurTuple help us to delete matched tuples in HashTable.designed for Right Semi/Anti Join */
|
|
HashJoinTuple hj_PreTuple;
|
|
TupleTableSlot* hj_OuterTupleSlot;
|
|
TupleTableSlot* hj_HashTupleSlot;
|
|
TupleTableSlot* hj_NullOuterTupleSlot;
|
|
TupleTableSlot* hj_NullInnerTupleSlot;
|
|
TupleTableSlot* hj_FirstOuterTupleSlot;
|
|
int hj_JoinState;
|
|
bool hj_MatchedOuter;
|
|
bool hj_OuterNotEmpty;
|
|
bool hj_streamBothSides;
|
|
bool hj_rebuildHashtable;
|
|
List* hj_hashCollations; /* list of collations OIDs */
|
|
#ifdef USE_SPQ
|
|
bool hj_nonequijoin; /* set true if force hash table to keep nulls */
|
|
bool hj_InnerEmpty; /* set to true if inner side is empty */
|
|
bool prefetch_inner;
|
|
bool is_set_op_join;
|
|
#endif
|
|
} HashJoinState;
|
|
|
|
/* ----------------------------------------------------------------
|
|
* Materialization State Information
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
|
|
/* ----------------
|
|
* MaterialState information
|
|
*
|
|
* materialize nodes are used to materialize the results
|
|
* of a subplan into a temporary file.
|
|
*
|
|
* ss.ss_ScanTupleSlot refers to output of underlying plan.
|
|
* ----------------
|
|
*/
|
|
typedef struct MaterialState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
int eflags; /* capability flags to pass to tuplestore */
|
|
bool eof_underlying; /* reached end of underlying plan? */
|
|
bool materalAll;
|
|
Tuplestorestate* tuplestorestate;
|
|
} MaterialState;
|
|
|
|
/* ----------------
|
|
* SortState information
|
|
* ----------------
|
|
*/
|
|
typedef struct SortState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
bool randomAccess; /* need random access to sort output? */
|
|
bool bounded; /* is the result set bounded? */
|
|
int64 bound; /* if bounded, how many tuples are needed */
|
|
bool sort_Done; /* sort completed yet? */
|
|
bool bounded_Done; /* value of bounded we did the sort with */
|
|
int64 bound_Done; /* value of bound we did the sort with */
|
|
void* tuplesortstate; /* private state of tuplesort.c */
|
|
int32 local_work_mem; /* work_mem local for this sort */
|
|
int sortMethodId; /* sort method for explain */
|
|
int spaceTypeId; /* space type for explain */
|
|
long spaceUsed; /* space used for explain */
|
|
int64* space_size; /* spill size for temp table */
|
|
} SortState;
|
|
|
|
struct SortGroupStatePriv;
|
|
/* ----------------
|
|
* SortGroupState information
|
|
* ----------------
|
|
*/
|
|
typedef struct SortGroupState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
int64 bound; /* if bounded, how many group are needed */
|
|
struct SortGroupStatePriv *state; /* private state of nodeSortGroup.c */
|
|
bool sort_Done; /* sort completed yet? */
|
|
bool *new_group_trigger; /* indicates new groups where returning tuples */
|
|
const char *spaceType; /* type of space spaceUsed represents */
|
|
int64 spaceUsed; /* space used for explain */
|
|
} SortGroupState;
|
|
|
|
/* ---------------------
|
|
* GroupState information
|
|
* -------------------------
|
|
*/
|
|
typedef struct GroupState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
FmgrInfo* eqfunctions; /* per-field lookup data for equality fns */
|
|
bool grp_done; /* indicates completion of Group scan */
|
|
} GroupState;
|
|
|
|
/* ---------------------
|
|
* AggState information
|
|
*
|
|
* ss.ss_ScanTupleSlot refers to output of underlying plan.
|
|
*
|
|
* Note: ss.ps.ps_ExprContext contains ecxt_aggvalues and
|
|
* ecxt_aggnulls arrays, which hold the computed agg values for the current
|
|
* input group during evaluation of an Agg node's output tuple(s). We
|
|
* create a second ExprContext, tmpcontext, in which to evaluate input
|
|
* expressions and run the aggregate transition functions.
|
|
* -------------------------
|
|
*/
|
|
/* these structs are private in nodeAgg.c: */
|
|
typedef struct AggStatePerAggData* AggStatePerAgg;
|
|
typedef struct AggStatePerAggForFlattenedExprData* AggStatePerAggForFlattenedExpr;
|
|
typedef struct AggStatePerTransData* AggStatePerTrans;
|
|
typedef struct AggStatePerGroupData* AggStatePerGroup;
|
|
typedef struct AggStatePerPhaseData* AggStatePerPhase;
|
|
|
|
typedef struct AggState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
List* aggs; /* all Aggref nodes in targetlist & quals */
|
|
int numaggs; /* length of list (could be zero!) */
|
|
AggStatePerPhase phase; /* pointer to current phase data */
|
|
int numphases; /* number of phases */
|
|
int current_phase; /* current phase number */
|
|
FmgrInfo* hashfunctions; /* per-grouping-field hash fns */
|
|
AggStatePerAgg peragg; /* per-Aggref information */
|
|
MemoryContext* aggcontexts; /* memory context for long-lived data */
|
|
ExprContext* tmpcontext; /* econtext for input expressions */
|
|
#ifdef USE_SPQ
|
|
AggSplit aggsplittype; /* agg-splitting mode, see nodes.h */
|
|
#endif
|
|
AggStatePerAgg curperagg; /* identifies currently active aggregate */
|
|
bool input_done; /* indicates end of input */
|
|
bool agg_done; /* indicates completion of Agg scan */
|
|
bool new_group_trigger; /* indicates new groups where returning tuples*/
|
|
int projected_set; /* The last projected grouping set */
|
|
int current_set; /* The current grouping set being evaluated */
|
|
Bitmapset* grouped_cols; /* grouped cols in current projection */
|
|
List* all_grouped_cols; /* list of all grouped cols in DESC order */
|
|
/* These fields are for grouping set phase data */
|
|
int maxsets; /* The max number of sets in any phase */
|
|
AggStatePerPhase phases; /* array of all phases */
|
|
Tuplesortstate* sort_in; /* sorted input to phases > 0 */
|
|
Tuplesortstate* sort_out; /* input is copied here for next phase */
|
|
TupleTableSlot* sort_slot; /* slot for sort results */
|
|
/* these fields are used in AGG_PLAIN and AGG_SORTED modes: */
|
|
AggStatePerGroup pergroup; /* per-Aggref-per-group working state */
|
|
HeapTuple grp_firstTuple; /* copy of first tuple of current group */
|
|
/* these fields are used in AGG_HASHED mode: */
|
|
TupleHashTable hashtable; /* hash table with one entry per group */
|
|
TupleTableSlot* hashslot; /* slot for loading hash table */
|
|
List* hash_needed; /* list of columns needed in hash table */
|
|
bool table_filled; /* hash table filled yet? */
|
|
TupleHashIterator hashiter; /* for iterating through hash table */
|
|
#ifdef PGXC
|
|
bool is_final; /* apply the final step for aggregates */
|
|
#endif /* PGXC */
|
|
void* aggTempFileControl;
|
|
FmgrInfo* eqfunctions; /* per-grouping-field equality fns */
|
|
/* support for evaluation of agg inputs */
|
|
TupleTableSlot *evalslot; /* slot for agg inputs */
|
|
ProjectionInfo *evalproj; /* projection machinery */
|
|
TupleDesc evaldesc; /* descriptor of input tuples */
|
|
|
|
int numtrans; /* number of pertrans items */
|
|
AggStrategy aggstrategy; /* strategy mode */
|
|
AggStatePerAggForFlattenedExpr peragg_flattened; /* per-Aggref information for flattened expression*/
|
|
AggStatePerTrans pertrans; /* per-Trans state information */
|
|
MemoryContext curaggcontext; /* currently active aggcontext */
|
|
AggStatePerTrans curpertrans; /* currently active trans state */
|
|
int num_hashes;
|
|
AggStatePerGroup hash_pergroup; /* grouping set indexed array of* per-group pointers */
|
|
AggStatePerGroup all_pergroups; /* array of first ->pergroups, than * ->hash_pergroup */
|
|
|
|
TupleTableSlot* ndp_slot; /* slot for load ndp data */
|
|
} AggState;
|
|
|
|
/* ----------------
|
|
* WindowAggState information
|
|
* ----------------
|
|
*/
|
|
/* these structs are private in nodeWindowAgg.c: */
|
|
typedef struct WindowStatePerFuncData* WindowStatePerFunc;
|
|
typedef struct WindowStatePerAggData* WindowStatePerAgg;
|
|
|
|
typedef struct WindowAggState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
|
|
/* these fields are filled in by ExecInitExpr: */
|
|
List* funcs; /* all WindowFunc nodes in targetlist */
|
|
int numfuncs; /* total number of window functions */
|
|
int numaggs; /* number that are plain aggregates */
|
|
|
|
WindowStatePerFunc perfunc; /* per-window-function information */
|
|
WindowStatePerAgg peragg; /* per-plain-aggregate information */
|
|
FmgrInfo* partEqfunctions; /* equality funcs for partition columns */
|
|
FmgrInfo* ordEqfunctions; /* equality funcs for ordering columns */
|
|
Tuplestorestate* buffer; /* stores rows of current partition */
|
|
int current_ptr; /* read pointer # for current */
|
|
int64 spooled_rows; /* total # of rows in buffer */
|
|
int64 currentpos; /* position of current row in partition */
|
|
int64 frameheadpos; /* current frame head position */
|
|
int64 frametailpos; /* current frame tail position */
|
|
/* use struct pointer to avoid including windowapi.h here */
|
|
struct WindowObjectData* agg_winobj; /* winobj for aggregate fetches */
|
|
int64 aggregatedbase; /* start row for current aggregates */
|
|
int64 aggregatedupto; /* rows before this one are aggregated */
|
|
|
|
int frameOptions; /* frame_clause options, see WindowDef */
|
|
ExprState* startOffset; /* expression for starting bound offset */
|
|
ExprState* endOffset; /* expression for ending bound offset */
|
|
Datum startOffsetValue; /* result of startOffset evaluation */
|
|
Datum endOffsetValue; /* result of endOffset evaluation */
|
|
|
|
MemoryContext partcontext; /* context for partition-lifespan data */
|
|
MemoryContext aggcontext; /* context for each aggregate data */
|
|
ExprContext* tmpcontext; /* short-term evaluation context */
|
|
|
|
bool all_first; /* true if the scan is starting */
|
|
bool all_done; /* true if the scan is finished */
|
|
bool partition_spooled; /* true if all tuples in current partition have been spooled into tuplestore */
|
|
bool more_partitions; /* true if there's more partitions after this one */
|
|
bool framehead_valid; /* true if frameheadpos is known up to date for current row */
|
|
bool frametail_valid; /* true if frametailpos is known up to date for current row */
|
|
|
|
TupleTableSlot* first_part_slot; /* first tuple of current or next partition */
|
|
|
|
/* temporary slots for tuples fetched back from tuplestore */
|
|
TupleTableSlot* agg_row_slot;
|
|
TupleTableSlot* temp_slot_1;
|
|
TupleTableSlot* temp_slot_2;
|
|
} WindowAggState;
|
|
|
|
/* ----------------
|
|
* OrderedSetAggState information
|
|
* ----------------
|
|
*/
|
|
typedef struct OrderedSetAggState {
|
|
AggState* aggstate;
|
|
Aggref* aggref; /* Keep the agg info for start up used */
|
|
Tuplesortstate* sortstate; /* Used for accumulate sort datum */
|
|
int64 number_of_rows; /* Number of normal datum inside sortstate */
|
|
TupleDesc tupdesc; /* Tuple descriptor for datum inside sortstate */
|
|
|
|
Oid datumtype; /* Datatype of datums being sorted */
|
|
int16 typLen;
|
|
bool typByVal;
|
|
char typAlign;
|
|
Oid eq_operator; /* Equality operator associated with sort operator */
|
|
char sign; /* Sign for orderedSetAggState */
|
|
} OrderedSetAggState;
|
|
|
|
/* ----------------
|
|
* UniqueState information
|
|
*
|
|
* Unique nodes are used "on top of" sort nodes to discard
|
|
* duplicate tuples returned from the sort phase. Basically
|
|
* all it does is compare the current tuple from the subplan
|
|
* with the previously fetched tuple (stored in its result slot).
|
|
* If the two are identical in all interesting fields, then
|
|
* we just fetch another tuple from the sort and try again.
|
|
* ----------------
|
|
*/
|
|
typedef struct UniqueState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
FmgrInfo* eqfunctions; /* per-field lookup data for equality fns */
|
|
MemoryContext tempContext; /* short-term context for comparisons */
|
|
} UniqueState;
|
|
|
|
/* ----------------
|
|
* HashState information
|
|
* ----------------
|
|
*/
|
|
typedef struct HashState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
HashJoinTable hashtable; /* hash table for the hashjoin */
|
|
List* hashkeys; /* list of ExprState nodes */
|
|
int32 local_work_mem; /* work_mem local for this hash join */
|
|
int64 spill_size;
|
|
#ifdef USE_SPQ
|
|
bool hs_keepnull; /* Keep nulls */
|
|
bool hs_quit_if_hashkeys_null; /* quit building hash table if hashkeys are all null */
|
|
bool hs_hashkeys_null; /* found an instance wherein hashkeys are all null */
|
|
#endif
|
|
/* hashkeys is same as parent's hj_InnerHashKeys */
|
|
} HashState;
|
|
|
|
/* ----------------
|
|
* SetOpState information
|
|
*
|
|
* Even in "sorted" mode, SetOp nodes are more complex than a simple
|
|
* Unique, since we have to count how many duplicates to return. But
|
|
* we also support hashing, so this is really more like a cut-down
|
|
* form of Agg.
|
|
* ----------------
|
|
*/
|
|
/* this struct is private in nodeSetOp.c: */
|
|
typedef struct SetOpStatePerGroupData* SetOpStatePerGroup;
|
|
|
|
typedef struct SetOpState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
FmgrInfo* eqfunctions; /* per-grouping-field equality fns */
|
|
FmgrInfo* hashfunctions; /* per-grouping-field hash fns */
|
|
bool setop_done; /* indicates completion of output scan */
|
|
long numOutput; /* number of dups left to output */
|
|
MemoryContext tempContext; /* short-term context for comparisons */
|
|
/* these fields are used in SETOP_SORTED mode: */
|
|
SetOpStatePerGroup pergroup; /* per-group working state */
|
|
HeapTuple grp_firstTuple; /* copy of first tuple of current group */
|
|
/* these fields are used in SETOP_HASHED mode: */
|
|
TupleHashTable hashtable; /* hash table with one entry per group */
|
|
MemoryContext tableContext; /* memory context containing hash table */
|
|
bool table_filled; /* hash table filled yet? */
|
|
TupleHashIterator hashiter; /* for iterating through hash table */
|
|
void* TempFileControl;
|
|
int64 spill_size;
|
|
} SetOpState;
|
|
|
|
/* ----------------
|
|
* LockRowsState information
|
|
*
|
|
* LockRows nodes are used to enforce FOR [KEY] UPDATE/FOR SHARE locking.
|
|
* ----------------
|
|
*/
|
|
typedef struct LockRowsState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
List* lr_arowMarks; /* List of ExecAuxRowMarks */
|
|
EPQState lr_epqstate; /* for evaluating EvalPlanQual rechecks */
|
|
} LockRowsState;
|
|
|
|
/* ----------------
|
|
* LimitState information
|
|
*
|
|
* Limit nodes are used to enforce LIMIT/OFFSET clauses.
|
|
* They just select the desired subrange of their subplan's output.
|
|
*
|
|
* offset is the number of initial tuples to skip (0 does nothing).
|
|
* count is the number of tuples to return after skipping the offset tuples.
|
|
* If no limit count was specified, count is undefined and noCount is true.
|
|
* When lstate == LIMIT_INITIAL, offset/count/noCount haven't been set yet.
|
|
* ----------------
|
|
*/
|
|
typedef enum {
|
|
LIMIT_INITIAL, /* initial state for LIMIT node */
|
|
LIMIT_RESCAN, /* rescan after recomputing parameters */
|
|
LIMIT_EMPTY, /* there are no returnable rows */
|
|
LIMIT_INWINDOW, /* have returned a row in the window */
|
|
LIMIT_SUBPLANEOF, /* at EOF of subplan (within window) */
|
|
LIMIT_WINDOWEND, /* stepped off end of window */
|
|
LIMIT_WINDOWSTART /* stepped off beginning of window */
|
|
} LimitStateCond;
|
|
|
|
typedef struct LimitState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
ExprState* limitOffset; /* OFFSET parameter, or NULL if none */
|
|
ExprState* limitCount; /* COUNT parameter, or NULL if none */
|
|
int64 offset; /* current OFFSET value */
|
|
int64 count; /* current COUNT, if any */
|
|
bool noCount; /* if true, ignore count */
|
|
LimitStateCond lstate; /* state machine status, as above */
|
|
int64 position; /* 1-based index of last tuple returned */
|
|
TupleTableSlot* subSlot; /* tuple last obtained from subplan */
|
|
} LimitState;
|
|
|
|
/*
|
|
* Target : data partition
|
|
* Brief : structure definition about partition iteration
|
|
*/
|
|
typedef struct PartIteratorState {
|
|
PlanState ps; /* its first field is NodeTag */
|
|
int currentItr; /* the sequence number for processing partition */
|
|
int subPartCurrentItr; /* the sequence number for processing partition */
|
|
} PartIteratorState;
|
|
|
|
struct VecLimitState : public LimitState {
|
|
VectorBatch* subBatch;
|
|
};
|
|
|
|
/*
|
|
* RownumState node: used for computing the pseudo-column ROWNUM
|
|
*/
|
|
typedef struct RownumState {
|
|
ExprState xprstate;
|
|
PlanState* ps; /* the value of ROWNUM depends on its parent PlanState */
|
|
} RownumState;
|
|
|
|
typedef struct UserSetElemState {
|
|
ExprState xprstate;
|
|
UserSetElem* use;
|
|
ExprState* instate;
|
|
} UserSetElemState;
|
|
|
|
typedef struct PrefixKeyState {
|
|
ExprState xprstate;
|
|
ExprState* arg; /* state of my child node */
|
|
int encoding;
|
|
} PrefixKeyState;
|
|
|
|
/* ----------------
|
|
* GroupingFuncExprState node
|
|
*
|
|
* The list of column numbers refers to the input tuples of the Agg node to
|
|
* which the GroupingFunc belongs, and may contain 0 for references to columns
|
|
* that are only present in grouping sets processed by different Agg nodes (and
|
|
* which are therefore always considered "grouping" here).
|
|
* ----------------
|
|
*/
|
|
typedef struct GroupingFuncExprState {
|
|
ExprState xprstate;
|
|
AggState* aggstate;
|
|
List* clauses; /* integer list of column numbers */
|
|
} GroupingFuncExprState;
|
|
|
|
typedef struct GroupingIdExprState {
|
|
ExprState xprstate;
|
|
AggState* aggstate;
|
|
} GroupingIdExprState;
|
|
|
|
/*
|
|
* used by CstoreInsert in nodeModifyTable.h and vecmodifytable.cpp
|
|
*/
|
|
#define FLUSH_DATA(obj, type) \
|
|
do { \
|
|
((type*)obj)->SetEndFlag(); \
|
|
((type*)obj)->BatchInsert((VectorBatch*)NULL, 0); \
|
|
((type*)obj)->EndBatchInsert(); \
|
|
((type*)obj)->Destroy(); \
|
|
delete (type*)obj; \
|
|
} while (0)
|
|
|
|
/*
|
|
* used by TsStoreInsert in nodeModifyTable.h and vecmodifytable.cpp
|
|
*/
|
|
#define FLUSH_DATA_TSDB(obj, type) \
|
|
do{ \
|
|
((type*)obj)->BatchInsert((VectorBatch*)NULL, 0); \
|
|
((type*)obj)->end_batch_insert(); \
|
|
((type*)obj)->Destroy(); \
|
|
}while(0)
|
|
/*
|
|
* record the first tuple time used by INSERT, UPDATE and DELETE in ExecModifyTable and ExecVecModifyTable
|
|
*/
|
|
#define record_first_time() \
|
|
do { \
|
|
if (unlikely(is_first_modified)) { \
|
|
INSTR_TIME_SET_CURRENT(node->first_tuple_modified); \
|
|
is_first_modified = false; \
|
|
} \
|
|
} while (0)
|
|
|
|
extern TupleTableSlot* ExecMakeTupleSlot(Tuple tuple, TableScanDesc tableScan, TupleTableSlot* slot, const TableAmRoutine* tam_ops);
|
|
|
|
/*
|
|
* When the global partition index is used for bitmap scanning,
|
|
* checks whether the partition table needs to be
|
|
* switched each time an tbmres is obtained.
|
|
*/
|
|
inline bool BitmapNodeNeedSwitchPartRel(BitmapHeapScanState* node)
|
|
{
|
|
return tbm_is_global(node->tbm) && GPIScanCheckPartOid(node->gpi_scan, node->tbmres->partitionOid);
|
|
}
|
|
|
|
// DB4AI state node
|
|
|
|
struct AlgorithmAPI;
|
|
struct TrainModelState;
|
|
|
|
typedef struct ModelTuple {
|
|
Datum *values; // attributes value
|
|
bool *isnull; // whether an attribute is null
|
|
Oid *typid; // type of an attribute
|
|
bool *typbyval; // attribute is passed by value or by reference
|
|
int16 *typlen; // the length of an attribute
|
|
int ncolumns; // number of attributes
|
|
} ModelTuple;
|
|
|
|
// returns the next data row, or nullptr when iteration has finished
|
|
typedef bool (*callback_ml_fetch)(void *callback_data, ModelTuple *tuple);
|
|
|
|
// restarts the iteration of the dataset without fetching any tuple at all
|
|
typedef void (*callback_ml_rescan)(void *callback_data);
|
|
|
|
typedef struct TrainModelState {
|
|
ScanState ss; /* its first field is NodeTag */
|
|
const TrainModel *config;
|
|
AlgorithmAPI *algorithm;
|
|
int finished; // number of configurations still running
|
|
// row data
|
|
ModelTuple tuple; // data as well as metadata
|
|
bool row_allocated;
|
|
// utility functions
|
|
callback_ml_fetch fetch;
|
|
callback_ml_rescan rescan;
|
|
void *callback_data; // for direct ML, used by the fetch callback
|
|
} TrainModelState;
|
|
#endif /* EXECNODES_H */
|
|
|