/* -------------------------------------------------------------------------
 *
 * 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 */

    bool withLimitCount; /* true if delete with limit, false if only delete without limit, only apply for b-db */

    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
    bool compileCodegen;
} 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;
    List *keep_args;
    bool keep_first;
} 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* fmtstr;    /* format string */
    char* nlsfmtstr; /* nls format string */
    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 */
    char* fmtstr;     /* format string */
    char* nlsfmtstr;  /* nls format string */
    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 */
    char* fmtstr;       /* format string */
    char* nlsfmtstr;    /* nsl format string */
    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 */
    List* cmpargs;     /* the comparison 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;

/* ----------------
 *		NanTestState node
 * ----------------
 */
typedef struct NanTestState {
    ExprState xprstate;
    ExprState* arg; /* input expression */
} NanTestState;

/* ----------------
 *		InfiniteTestState node
 * ----------------
 */
typedef struct InfiniteTestState {
    ExprState xprstate;
    ExprState* arg; /* input expression */
} InfiniteTestState;

/* ----------------
 *		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;

typedef struct SWDfsOpState
{
    List**          prior_key_stack;
    List**          tuples_stack;
    int             stack_size;
    int             cur_level;
    int             cur_rownum;
    TupleTableSlot* last_ru_slot;
} SWDfsOpState;

/* ----------------
 *	 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;
    List*               connect_by_qual;
    List*               start_with_qual;
    SWDfsOpState*       dfs_state;
} 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;

/* ----------------
 *	 AnnIndexScanState 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 AnnIndexScanState {
    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;
    double annCount; // limitValue/selectvity
} AnnIndexScanState;

/* ----------------
 *	 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)

/* ----------------
 *	 TidRangeScanState information
 *
 *		trss_tidexprs		list of TidOpExpr structs (see nodeTidrangescan.c)
 *		trss_mintid			the lowest TID in the scan range
 *		trss_maxtid			the highest TID in the scan range
 *		trss_inScan			is a scan currently in progress?
 * ----------------
 */
typedef struct TidRangeScanState
{
    ScanState	ss;                /* its first field is NodeTag */
    List	   *trss_tidexprs;
    ItemPointerData trss_mintid;
    ItemPointerData trss_maxtid;
    bool		trss_inScan;
} TidRangeScanState;

/* ----------------
 *	 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 */
    TupleTableSlot *tupslot;   /* Tuple slot we can use for inserting/extracting tuples: */

    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 */
    bool isPercent;          /* COUNT is a percentage */
    bool withTies;           /* whether to include ties */

    int numCols;            /* number of sort-key columns */
    AttrNumber* sortColIdx; /* their indexes in the target list */
    Oid* collations;        /* OIDs of collations */
    
    FmgrInfo* eqfunctions;     /* per-field lookup data for equality fns */
    MemoryContext tempContext; /* short-term context for comparisons */
    int64 offset;            /* current OFFSET value */
    int64 count;             /* current COUNT, if any */
    float8 fraction;         /* current fraction, if any */
    bool noCount;            /* if true, ignore count */
    TupleTableSlot* outputSlot; /* store the last tuple slot where position == count */
    Tuplestorestate* tuplestorestate;   /* store for all the results from subplan */
    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;

typedef struct CursorExpressionState {
    ExprState xprstate;
    CursorExpression* cursor_expression;
    List* param;
} CursorExpressionState;


#endif /* EXECNODES_H */