summaryrefslogtreecommitdiffstats
path: root/src/include/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/executor')
-rw-r--r--src/include/executor/execAsync.h25
-rw-r--r--src/include/executor/execExpr.h782
-rw-r--r--src/include/executor/execParallel.h51
-rw-r--r--src/include/executor/execPartition.h128
-rw-r--r--src/include/executor/execdebug.h130
-rw-r--r--src/include/executor/execdesc.h70
-rw-r--r--src/include/executor/executor.h661
-rw-r--r--src/include/executor/functions.h55
-rw-r--r--src/include/executor/hashjoin.h362
-rw-r--r--src/include/executor/instrument.h116
-rw-r--r--src/include/executor/nodeAgg.h333
-rw-r--r--src/include/executor/nodeAppend.h30
-rw-r--r--src/include/executor/nodeBitmapAnd.h24
-rw-r--r--src/include/executor/nodeBitmapHeapscan.h32
-rw-r--r--src/include/executor/nodeBitmapIndexscan.h24
-rw-r--r--src/include/executor/nodeBitmapOr.h24
-rw-r--r--src/include/executor/nodeCtescan.h23
-rw-r--r--src/include/executor/nodeCustom.h42
-rw-r--r--src/include/executor/nodeForeignscan.h38
-rw-r--r--src/include/executor/nodeFunctionscan.h23
-rw-r--r--src/include/executor/nodeGather.h24
-rw-r--r--src/include/executor/nodeGatherMerge.h26
-rw-r--r--src/include/executor/nodeGroup.h23
-rw-r--r--src/include/executor/nodeHash.h79
-rw-r--r--src/include/executor/nodeHashjoin.h34
-rw-r--r--src/include/executor/nodeIncrementalSort.h28
-rw-r--r--src/include/executor/nodeIndexonlyscan.h36
-rw-r--r--src/include/executor/nodeIndexscan.h47
-rw-r--r--src/include/executor/nodeLimit.h23
-rw-r--r--src/include/executor/nodeLockRows.h23
-rw-r--r--src/include/executor/nodeMaterial.h25
-rw-r--r--src/include/executor/nodeMemoize.h32
-rw-r--r--src/include/executor/nodeMergeAppend.h23
-rw-r--r--src/include/executor/nodeMergejoin.h23
-rw-r--r--src/include/executor/nodeModifyTable.h26
-rw-r--r--src/include/executor/nodeNamedtuplestorescan.h23
-rw-r--r--src/include/executor/nodeNestloop.h23
-rw-r--r--src/include/executor/nodeProjectSet.h23
-rw-r--r--src/include/executor/nodeRecursiveunion.h23
-rw-r--r--src/include/executor/nodeResult.h25
-rw-r--r--src/include/executor/nodeSamplescan.h23
-rw-r--r--src/include/executor/nodeSeqscan.h31
-rw-r--r--src/include/executor/nodeSetOp.h23
-rw-r--r--src/include/executor/nodeSort.h32
-rw-r--r--src/include/executor/nodeSubplan.h29
-rw-r--r--src/include/executor/nodeSubqueryscan.h23
-rw-r--r--src/include/executor/nodeTableFuncscan.h23
-rw-r--r--src/include/executor/nodeTidrangescan.h24
-rw-r--r--src/include/executor/nodeTidscan.h23
-rw-r--r--src/include/executor/nodeUnique.h23
-rw-r--r--src/include/executor/nodeValuesscan.h23
-rw-r--r--src/include/executor/nodeWindowAgg.h23
-rw-r--r--src/include/executor/nodeWorktablescan.h23
-rw-r--r--src/include/executor/spi.h213
-rw-r--r--src/include/executor/spi_priv.h105
-rw-r--r--src/include/executor/tablefunc.h67
-rw-r--r--src/include/executor/tqueue.h32
-rw-r--r--src/include/executor/tstoreReceiver.h31
-rw-r--r--src/include/executor/tuptable.h487
59 files changed, 4820 insertions, 0 deletions
diff --git a/src/include/executor/execAsync.h b/src/include/executor/execAsync.h
new file mode 100644
index 0000000..7551b55
--- /dev/null
+++ b/src/include/executor/execAsync.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ * execAsync.h
+ * Support functions for asynchronous execution
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/executor/execAsync.h
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef EXECASYNC_H
+#define EXECASYNC_H
+
+#include "nodes/execnodes.h"
+
+extern void ExecAsyncRequest(AsyncRequest *areq);
+extern void ExecAsyncConfigureWait(AsyncRequest *areq);
+extern void ExecAsyncNotify(AsyncRequest *areq);
+extern void ExecAsyncResponse(AsyncRequest *areq);
+extern void ExecAsyncRequestDone(AsyncRequest *areq, TupleTableSlot *result);
+extern void ExecAsyncRequestPending(AsyncRequest *areq);
+
+#endif /* EXECASYNC_H */
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
new file mode 100644
index 0000000..785600d
--- /dev/null
+++ b/src/include/executor/execExpr.h
@@ -0,0 +1,782 @@
+/*-------------------------------------------------------------------------
+ *
+ * execExpr.h
+ * Low level infrastructure related to expression evaluation
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/execExpr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXEC_EXPR_H
+#define EXEC_EXPR_H
+
+#include "executor/nodeAgg.h"
+#include "nodes/execnodes.h"
+
+/* forward references to avoid circularity */
+struct ExprEvalStep;
+struct SubscriptingRefState;
+struct ScalarArrayOpExprHashTable;
+
+/* Bits in ExprState->flags (see also execnodes.h for public flag bits): */
+/* expression's interpreter has been initialized */
+#define EEO_FLAG_INTERPRETER_INITIALIZED (1 << 1)
+/* jump-threading is in use */
+#define EEO_FLAG_DIRECT_THREADED (1 << 2)
+
+/* Typical API for out-of-line evaluation subroutines */
+typedef void (*ExecEvalSubroutine) (ExprState *state,
+ struct ExprEvalStep *op,
+ ExprContext *econtext);
+
+/* API for out-of-line evaluation subroutines returning bool */
+typedef bool (*ExecEvalBoolSubroutine) (ExprState *state,
+ struct ExprEvalStep *op,
+ ExprContext *econtext);
+
+/* ExprEvalSteps that cache a composite type's tupdesc need one of these */
+/* (it fits in-line in some step types, otherwise allocate out-of-line) */
+typedef struct ExprEvalRowtypeCache
+{
+ /*
+ * cacheptr points to composite type's TypeCacheEntry if tupdesc_id is not
+ * 0; or for an anonymous RECORD type, it points directly at the cached
+ * tupdesc for the type, and tupdesc_id is 0. (We'd use separate fields
+ * if space were not at a premium.) Initial state is cacheptr == NULL.
+ */
+ void *cacheptr;
+ uint64 tupdesc_id; /* last-seen tupdesc identifier, or 0 */
+} ExprEvalRowtypeCache;
+
+/*
+ * Discriminator for ExprEvalSteps.
+ *
+ * Identifies the operation to be executed and which member in the
+ * ExprEvalStep->d union is valid.
+ *
+ * The order of entries needs to be kept in sync with the dispatch_table[]
+ * array in execExprInterp.c:ExecInterpExpr().
+ */
+typedef enum ExprEvalOp
+{
+ /* entire expression has been evaluated completely, return */
+ EEOP_DONE,
+
+ /* apply slot_getsomeattrs on corresponding tuple slot */
+ EEOP_INNER_FETCHSOME,
+ EEOP_OUTER_FETCHSOME,
+ EEOP_SCAN_FETCHSOME,
+
+ /* compute non-system Var value */
+ EEOP_INNER_VAR,
+ EEOP_OUTER_VAR,
+ EEOP_SCAN_VAR,
+
+ /* compute system Var value */
+ EEOP_INNER_SYSVAR,
+ EEOP_OUTER_SYSVAR,
+ EEOP_SCAN_SYSVAR,
+
+ /* compute wholerow Var */
+ EEOP_WHOLEROW,
+
+ /*
+ * Compute non-system Var value, assign it into ExprState's resultslot.
+ * These are not used if a CheckVarSlotCompatibility() check would be
+ * needed.
+ */
+ EEOP_ASSIGN_INNER_VAR,
+ EEOP_ASSIGN_OUTER_VAR,
+ EEOP_ASSIGN_SCAN_VAR,
+
+ /* assign ExprState's resvalue/resnull to a column of its resultslot */
+ EEOP_ASSIGN_TMP,
+ /* ditto, applying MakeExpandedObjectReadOnly() */
+ EEOP_ASSIGN_TMP_MAKE_RO,
+
+ /* evaluate Const value */
+ EEOP_CONST,
+
+ /*
+ * Evaluate function call (including OpExprs etc). For speed, we
+ * distinguish in the opcode whether the function is strict and/or
+ * requires usage stats tracking.
+ */
+ EEOP_FUNCEXPR,
+ EEOP_FUNCEXPR_STRICT,
+ EEOP_FUNCEXPR_FUSAGE,
+ EEOP_FUNCEXPR_STRICT_FUSAGE,
+
+ /*
+ * Evaluate boolean AND expression, one step per subexpression. FIRST/LAST
+ * subexpressions are special-cased for performance. Since AND always has
+ * at least two subexpressions, FIRST and LAST never apply to the same
+ * subexpression.
+ */
+ EEOP_BOOL_AND_STEP_FIRST,
+ EEOP_BOOL_AND_STEP,
+ EEOP_BOOL_AND_STEP_LAST,
+
+ /* similarly for boolean OR expression */
+ EEOP_BOOL_OR_STEP_FIRST,
+ EEOP_BOOL_OR_STEP,
+ EEOP_BOOL_OR_STEP_LAST,
+
+ /* evaluate boolean NOT expression */
+ EEOP_BOOL_NOT_STEP,
+
+ /* simplified version of BOOL_AND_STEP for use by ExecQual() */
+ EEOP_QUAL,
+
+ /* unconditional jump to another step */
+ EEOP_JUMP,
+
+ /* conditional jumps based on current result value */
+ EEOP_JUMP_IF_NULL,
+ EEOP_JUMP_IF_NOT_NULL,
+ EEOP_JUMP_IF_NOT_TRUE,
+
+ /* perform NULL tests for scalar values */
+ EEOP_NULLTEST_ISNULL,
+ EEOP_NULLTEST_ISNOTNULL,
+
+ /* perform NULL tests for row values */
+ EEOP_NULLTEST_ROWISNULL,
+ EEOP_NULLTEST_ROWISNOTNULL,
+
+ /* evaluate a BooleanTest expression */
+ EEOP_BOOLTEST_IS_TRUE,
+ EEOP_BOOLTEST_IS_NOT_TRUE,
+ EEOP_BOOLTEST_IS_FALSE,
+ EEOP_BOOLTEST_IS_NOT_FALSE,
+
+ /* evaluate PARAM_EXEC/EXTERN parameters */
+ EEOP_PARAM_EXEC,
+ EEOP_PARAM_EXTERN,
+ EEOP_PARAM_CALLBACK,
+
+ /* return CaseTestExpr value */
+ EEOP_CASE_TESTVAL,
+
+ /* apply MakeExpandedObjectReadOnly() to target value */
+ EEOP_MAKE_READONLY,
+
+ /* evaluate assorted special-purpose expression types */
+ EEOP_IOCOERCE,
+ EEOP_DISTINCT,
+ EEOP_NOT_DISTINCT,
+ EEOP_NULLIF,
+ EEOP_SQLVALUEFUNCTION,
+ EEOP_CURRENTOFEXPR,
+ EEOP_NEXTVALUEEXPR,
+ EEOP_ARRAYEXPR,
+ EEOP_ARRAYCOERCE,
+ EEOP_ROW,
+
+ /*
+ * Compare two individual elements of each of two compared ROW()
+ * expressions. Skip to ROWCOMPARE_FINAL if elements are not equal.
+ */
+ EEOP_ROWCOMPARE_STEP,
+
+ /* evaluate boolean value based on previous ROWCOMPARE_STEP operations */
+ EEOP_ROWCOMPARE_FINAL,
+
+ /* evaluate GREATEST() or LEAST() */
+ EEOP_MINMAX,
+
+ /* evaluate FieldSelect expression */
+ EEOP_FIELDSELECT,
+
+ /*
+ * Deform tuple before evaluating new values for individual fields in a
+ * FieldStore expression.
+ */
+ EEOP_FIELDSTORE_DEFORM,
+
+ /*
+ * Form the new tuple for a FieldStore expression. Individual fields will
+ * have been evaluated into columns of the tuple deformed by the preceding
+ * DEFORM step.
+ */
+ EEOP_FIELDSTORE_FORM,
+
+ /* Process container subscripts; possibly short-circuit result to NULL */
+ EEOP_SBSREF_SUBSCRIPTS,
+
+ /*
+ * Compute old container element/slice when a SubscriptingRef assignment
+ * expression contains SubscriptingRef/FieldStore subexpressions. Value is
+ * accessed using the CaseTest mechanism.
+ */
+ EEOP_SBSREF_OLD,
+
+ /* compute new value for SubscriptingRef assignment expression */
+ EEOP_SBSREF_ASSIGN,
+
+ /* compute element/slice for SubscriptingRef fetch expression */
+ EEOP_SBSREF_FETCH,
+
+ /* evaluate value for CoerceToDomainValue */
+ EEOP_DOMAIN_TESTVAL,
+
+ /* evaluate a domain's NOT NULL constraint */
+ EEOP_DOMAIN_NOTNULL,
+
+ /* evaluate a single domain CHECK constraint */
+ EEOP_DOMAIN_CHECK,
+
+ /* evaluate assorted special-purpose expression types */
+ EEOP_CONVERT_ROWTYPE,
+ EEOP_SCALARARRAYOP,
+ EEOP_HASHED_SCALARARRAYOP,
+ EEOP_XMLEXPR,
+ EEOP_AGGREF,
+ EEOP_GROUPING_FUNC,
+ EEOP_WINDOW_FUNC,
+ EEOP_SUBPLAN,
+
+ /* aggregation related nodes */
+ EEOP_AGG_STRICT_DESERIALIZE,
+ EEOP_AGG_DESERIALIZE,
+ EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
+ EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
+ EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
+ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,
+ EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL,
+ EEOP_AGG_PLAIN_TRANS_BYVAL,
+ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF,
+ EEOP_AGG_PLAIN_TRANS_STRICT_BYREF,
+ EEOP_AGG_PLAIN_TRANS_BYREF,
+ EEOP_AGG_ORDERED_TRANS_DATUM,
+ EEOP_AGG_ORDERED_TRANS_TUPLE,
+
+ /* non-existent operation, used e.g. to check array lengths */
+ EEOP_LAST
+} ExprEvalOp;
+
+
+typedef struct ExprEvalStep
+{
+ /*
+ * Instruction to be executed. During instruction preparation this is an
+ * enum ExprEvalOp, but later it can be changed to some other type, e.g. a
+ * pointer for computed goto (that's why it's an intptr_t).
+ */
+ intptr_t opcode;
+
+ /* where to store the result of this step */
+ Datum *resvalue;
+ bool *resnull;
+
+ /*
+ * Inline data for the operation. Inline data is faster to access, but
+ * also bloats the size of all instructions. The union should be kept to
+ * no more than 40 bytes on 64-bit systems (so that the entire struct is
+ * no more than 64 bytes, a single cacheline on common systems).
+ */
+ union
+ {
+ /* for EEOP_INNER/OUTER/SCAN_FETCHSOME */
+ struct
+ {
+ /* attribute number up to which to fetch (inclusive) */
+ int last_var;
+ /* will the type of slot be the same for every invocation */
+ bool fixed;
+ /* tuple descriptor, if known */
+ TupleDesc known_desc;
+ /* type of slot, can only be relied upon if fixed is set */
+ const TupleTableSlotOps *kind;
+ } fetch;
+
+ /* for EEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST] */
+ struct
+ {
+ /* attnum is attr number - 1 for regular VAR ... */
+ /* but it's just the normal (negative) attr number for SYSVAR */
+ int attnum;
+ Oid vartype; /* type OID of variable */
+ } var;
+
+ /* for EEOP_WHOLEROW */
+ struct
+ {
+ Var *var; /* original Var node in plan tree */
+ bool first; /* first time through, need to initialize? */
+ bool slow; /* need runtime check for nulls? */
+ TupleDesc tupdesc; /* descriptor for resulting tuples */
+ JunkFilter *junkFilter; /* JunkFilter to remove resjunk cols */
+ } wholerow;
+
+ /* for EEOP_ASSIGN_*_VAR */
+ struct
+ {
+ /* target index in ExprState->resultslot->tts_values/nulls */
+ int resultnum;
+ /* source attribute number - 1 */
+ int attnum;
+ } assign_var;
+
+ /* for EEOP_ASSIGN_TMP[_MAKE_RO] */
+ struct
+ {
+ /* target index in ExprState->resultslot->tts_values/nulls */
+ int resultnum;
+ } assign_tmp;
+
+ /* for EEOP_CONST */
+ struct
+ {
+ /* constant's value */
+ Datum value;
+ bool isnull;
+ } constval;
+
+ /* for EEOP_FUNCEXPR_* / NULLIF / DISTINCT */
+ struct
+ {
+ FmgrInfo *finfo; /* function's lookup data */
+ FunctionCallInfo fcinfo_data; /* arguments etc */
+ /* faster to access without additional indirection: */
+ PGFunction fn_addr; /* actual call address */
+ int nargs; /* number of arguments */
+ } func;
+
+ /* for EEOP_BOOL_*_STEP */
+ struct
+ {
+ bool *anynull; /* track if any input was NULL */
+ int jumpdone; /* jump here if result determined */
+ } boolexpr;
+
+ /* for EEOP_QUAL */
+ struct
+ {
+ int jumpdone; /* jump here on false or null */
+ } qualexpr;
+
+ /* for EEOP_JUMP[_CONDITION] */
+ struct
+ {
+ int jumpdone; /* target instruction's index */
+ } jump;
+
+ /* for EEOP_NULLTEST_ROWIS[NOT]NULL */
+ struct
+ {
+ /* cached descriptor for composite type - filled at runtime */
+ ExprEvalRowtypeCache rowcache;
+ } nulltest_row;
+
+ /* for EEOP_PARAM_EXEC/EXTERN */
+ struct
+ {
+ int paramid; /* numeric ID for parameter */
+ Oid paramtype; /* OID of parameter's datatype */
+ } param;
+
+ /* for EEOP_PARAM_CALLBACK */
+ struct
+ {
+ ExecEvalSubroutine paramfunc; /* add-on evaluation subroutine */
+ void *paramarg; /* private data for same */
+ int paramid; /* numeric ID for parameter */
+ Oid paramtype; /* OID of parameter's datatype */
+ } cparam;
+
+ /* for EEOP_CASE_TESTVAL/DOMAIN_TESTVAL */
+ struct
+ {
+ Datum *value; /* value to return */
+ bool *isnull;
+ } casetest;
+
+ /* for EEOP_MAKE_READONLY */
+ struct
+ {
+ Datum *value; /* value to coerce to read-only */
+ bool *isnull;
+ } make_readonly;
+
+ /* for EEOP_IOCOERCE */
+ struct
+ {
+ /* lookup and call info for source type's output function */
+ FmgrInfo *finfo_out;
+ FunctionCallInfo fcinfo_data_out;
+ /* lookup and call info for result type's input function */
+ FmgrInfo *finfo_in;
+ FunctionCallInfo fcinfo_data_in;
+ } iocoerce;
+
+ /* for EEOP_SQLVALUEFUNCTION */
+ struct
+ {
+ SQLValueFunction *svf;
+ } sqlvaluefunction;
+
+ /* for EEOP_NEXTVALUEEXPR */
+ struct
+ {
+ Oid seqid;
+ Oid seqtypid;
+ } nextvalueexpr;
+
+ /* for EEOP_ARRAYEXPR */
+ struct
+ {
+ Datum *elemvalues; /* element values get stored here */
+ bool *elemnulls;
+ int nelems; /* length of the above arrays */
+ Oid elemtype; /* array element type */
+ int16 elemlength; /* typlen of the array element type */
+ bool elembyval; /* is the element type pass-by-value? */
+ char elemalign; /* typalign of the element type */
+ bool multidims; /* is array expression multi-D? */
+ } arrayexpr;
+
+ /* for EEOP_ARRAYCOERCE */
+ struct
+ {
+ ExprState *elemexprstate; /* null if no per-element work */
+ Oid resultelemtype; /* element type of result array */
+ struct ArrayMapState *amstate; /* workspace for array_map */
+ } arraycoerce;
+
+ /* for EEOP_ROW */
+ struct
+ {
+ TupleDesc tupdesc; /* descriptor for result tuples */
+ /* workspace for the values constituting the row: */
+ Datum *elemvalues;
+ bool *elemnulls;
+ } row;
+
+ /* for EEOP_ROWCOMPARE_STEP */
+ struct
+ {
+ /* lookup and call data for column comparison function */
+ FmgrInfo *finfo;
+ FunctionCallInfo fcinfo_data;
+ PGFunction fn_addr;
+ /* target for comparison resulting in NULL */
+ int jumpnull;
+ /* target for comparison yielding inequality */
+ int jumpdone;
+ } rowcompare_step;
+
+ /* for EEOP_ROWCOMPARE_FINAL */
+ struct
+ {
+ RowCompareType rctype;
+ } rowcompare_final;
+
+ /* for EEOP_MINMAX */
+ struct
+ {
+ /* workspace for argument values */
+ Datum *values;
+ bool *nulls;
+ int nelems;
+ /* is it GREATEST or LEAST? */
+ MinMaxOp op;
+ /* lookup and call data for comparison function */
+ FmgrInfo *finfo;
+ FunctionCallInfo fcinfo_data;
+ } minmax;
+
+ /* for EEOP_FIELDSELECT */
+ struct
+ {
+ AttrNumber fieldnum; /* field number to extract */
+ Oid resulttype; /* field's type */
+ /* cached descriptor for composite type - filled at runtime */
+ ExprEvalRowtypeCache rowcache;
+ } fieldselect;
+
+ /* for EEOP_FIELDSTORE_DEFORM / FIELDSTORE_FORM */
+ struct
+ {
+ /* original expression node */
+ FieldStore *fstore;
+
+ /* cached descriptor for composite type - filled at runtime */
+ /* note that a DEFORM and FORM pair share the same cache */
+ ExprEvalRowtypeCache *rowcache;
+
+ /* workspace for column values */
+ Datum *values;
+ bool *nulls;
+ int ncolumns;
+ } fieldstore;
+
+ /* for EEOP_SBSREF_SUBSCRIPTS */
+ struct
+ {
+ ExecEvalBoolSubroutine subscriptfunc; /* evaluation subroutine */
+ /* too big to have inline */
+ struct SubscriptingRefState *state;
+ int jumpdone; /* jump here on null */
+ } sbsref_subscript;
+
+ /* for EEOP_SBSREF_OLD / ASSIGN / FETCH */
+ struct
+ {
+ ExecEvalSubroutine subscriptfunc; /* evaluation subroutine */
+ /* too big to have inline */
+ struct SubscriptingRefState *state;
+ } sbsref;
+
+ /* for EEOP_DOMAIN_NOTNULL / DOMAIN_CHECK */
+ struct
+ {
+ /* name of constraint */
+ char *constraintname;
+ /* where the result of a CHECK constraint will be stored */
+ Datum *checkvalue;
+ bool *checknull;
+ /* OID of domain type */
+ Oid resulttype;
+ } domaincheck;
+
+ /* for EEOP_CONVERT_ROWTYPE */
+ struct
+ {
+ Oid inputtype; /* input composite type */
+ Oid outputtype; /* output composite type */
+ /* these three fields are filled at runtime: */
+ ExprEvalRowtypeCache *incache; /* cache for input type */
+ ExprEvalRowtypeCache *outcache; /* cache for output type */
+ TupleConversionMap *map; /* column mapping */
+ } convert_rowtype;
+
+ /* for EEOP_SCALARARRAYOP */
+ struct
+ {
+ /* element_type/typlen/typbyval/typalign are filled at runtime */
+ Oid element_type; /* InvalidOid if not yet filled */
+ bool useOr; /* use OR or AND semantics? */
+ int16 typlen; /* array element type storage info */
+ bool typbyval;
+ char typalign;
+ FmgrInfo *finfo; /* function's lookup data */
+ FunctionCallInfo fcinfo_data; /* arguments etc */
+ /* faster to access without additional indirection: */
+ PGFunction fn_addr; /* actual call address */
+ } scalararrayop;
+
+ /* for EEOP_HASHED_SCALARARRAYOP */
+ struct
+ {
+ bool has_nulls;
+ struct ScalarArrayOpExprHashTable *elements_tab;
+ FmgrInfo *finfo; /* function's lookup data */
+ FunctionCallInfo fcinfo_data; /* arguments etc */
+ /* faster to access without additional indirection: */
+ PGFunction fn_addr; /* actual call address */
+ FmgrInfo *hash_finfo; /* function's lookup data */
+ FunctionCallInfo hash_fcinfo_data; /* arguments etc */
+ /* faster to access without additional indirection: */
+ PGFunction hash_fn_addr; /* actual call address */
+ } hashedscalararrayop;
+
+ /* for EEOP_XMLEXPR */
+ struct
+ {
+ XmlExpr *xexpr; /* original expression node */
+ /* workspace for evaluating named args, if any */
+ Datum *named_argvalue;
+ bool *named_argnull;
+ /* workspace for evaluating unnamed args, if any */
+ Datum *argvalue;
+ bool *argnull;
+ } xmlexpr;
+
+ /* for EEOP_AGGREF */
+ struct
+ {
+ int aggno;
+ } aggref;
+
+ /* for EEOP_GROUPING_FUNC */
+ struct
+ {
+ List *clauses; /* integer list of column numbers */
+ } grouping_func;
+
+ /* for EEOP_WINDOW_FUNC */
+ struct
+ {
+ /* out-of-line state, modified by nodeWindowAgg.c */
+ WindowFuncExprState *wfstate;
+ } window_func;
+
+ /* for EEOP_SUBPLAN */
+ struct
+ {
+ /* out-of-line state, created by nodeSubplan.c */
+ SubPlanState *sstate;
+ } subplan;
+
+ /* for EEOP_AGG_*DESERIALIZE */
+ struct
+ {
+ FunctionCallInfo fcinfo_data;
+ int jumpnull;
+ } agg_deserialize;
+
+ /* for EEOP_AGG_STRICT_INPUT_CHECK_NULLS / STRICT_INPUT_CHECK_ARGS */
+ struct
+ {
+ /*
+ * For EEOP_AGG_STRICT_INPUT_CHECK_ARGS args contains pointers to
+ * the NullableDatums that need to be checked for NULLs.
+ *
+ * For EEOP_AGG_STRICT_INPUT_CHECK_NULLS nulls contains pointers
+ * to booleans that need to be checked for NULLs.
+ *
+ * Both cases currently need to exist because sometimes the
+ * to-be-checked nulls are in TupleTableSlot.isnull array, and
+ * sometimes in FunctionCallInfoBaseData.args[i].isnull.
+ */
+ NullableDatum *args;
+ bool *nulls;
+ int nargs;
+ int jumpnull;
+ } agg_strict_input_check;
+
+ /* for EEOP_AGG_PLAIN_PERGROUP_NULLCHECK */
+ struct
+ {
+ int setoff;
+ int jumpnull;
+ } agg_plain_pergroup_nullcheck;
+
+ /* for EEOP_AGG_PLAIN_TRANS_[INIT_][STRICT_]{BYVAL,BYREF} */
+ /* for EEOP_AGG_ORDERED_TRANS_{DATUM,TUPLE} */
+ struct
+ {
+ AggStatePerTrans pertrans;
+ ExprContext *aggcontext;
+ int setno;
+ int transno;
+ int setoff;
+ } agg_trans;
+ } d;
+} ExprEvalStep;
+
+
+/* Non-inline data for container operations */
+typedef struct SubscriptingRefState
+{
+ bool isassignment; /* is it assignment, or just fetch? */
+
+ /* workspace for type-specific subscripting code */
+ void *workspace;
+
+ /* numupper and upperprovided[] are filled at expression compile time */
+ /* at runtime, subscripts are computed in upperindex[]/upperindexnull[] */
+ int numupper;
+ bool *upperprovided; /* indicates if this position is supplied */
+ Datum *upperindex;
+ bool *upperindexnull;
+
+ /* similarly for lower indexes, if any */
+ int numlower;
+ bool *lowerprovided;
+ Datum *lowerindex;
+ bool *lowerindexnull;
+
+ /* for assignment, new value to assign is evaluated into here */
+ Datum replacevalue;
+ bool replacenull;
+
+ /* if we have a nested assignment, sbs_fetch_old puts old value here */
+ Datum prevvalue;
+ bool prevnull;
+} SubscriptingRefState;
+
+/* Execution step methods used for SubscriptingRef */
+typedef struct SubscriptExecSteps
+{
+ /* See nodes/subscripting.h for more detail about these */
+ ExecEvalBoolSubroutine sbs_check_subscripts; /* process subscripts */
+ ExecEvalSubroutine sbs_fetch; /* fetch an element */
+ ExecEvalSubroutine sbs_assign; /* assign to an element */
+ ExecEvalSubroutine sbs_fetch_old; /* fetch old value for assignment */
+} SubscriptExecSteps;
+
+
+/* functions in execExpr.c */
+extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
+
+/* functions in execExprInterp.c */
+extern void ExecReadyInterpretedExpr(ExprState *state);
+extern ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op);
+
+extern Datum ExecInterpExprStillValid(ExprState *state, ExprContext *econtext, bool *isNull);
+extern void CheckExprStillValid(ExprState *state, ExprContext *econtext);
+
+/*
+ * Non fast-path execution functions. These are externs instead of statics in
+ * execExprInterp.c, because that allows them to be used by other methods of
+ * expression evaluation, reducing code duplication.
+ */
+extern void ExecEvalFuncExprFusage(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalParamExec(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalParamExtern(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalRowNull(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalRow(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalMinMax(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalSubPlan(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalSysVar(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext, TupleTableSlot *slot);
+
+extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup,
+ ExprContext *aggcontext);
+extern Datum ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
+ Datum newValue, bool newValueIsNull,
+ Datum oldValue, bool oldValueIsNull);
+extern void ExecEvalAggOrderedTransDatum(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+
+#endif /* EXEC_EXPR_H */
diff --git a/src/include/executor/execParallel.h b/src/include/executor/execParallel.h
new file mode 100644
index 0000000..3888175
--- /dev/null
+++ b/src/include/executor/execParallel.h
@@ -0,0 +1,51 @@
+/*--------------------------------------------------------------------
+ * execParallel.h
+ * POSTGRES parallel execution interface
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/executor/execParallel.h
+ *--------------------------------------------------------------------
+ */
+
+#ifndef EXECPARALLEL_H
+#define EXECPARALLEL_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
+#include "utils/dsa.h"
+
+typedef struct SharedExecutorInstrumentation SharedExecutorInstrumentation;
+
+typedef struct ParallelExecutorInfo
+{
+ PlanState *planstate; /* plan subtree we're running in parallel */
+ ParallelContext *pcxt; /* parallel context we're using */
+ BufferUsage *buffer_usage; /* points to bufusage area in DSM */
+ WalUsage *wal_usage; /* walusage area in DSM */
+ SharedExecutorInstrumentation *instrumentation; /* optional */
+ struct SharedJitInstrumentation *jit_instrumentation; /* optional */
+ dsa_area *area; /* points to DSA area in DSM */
+ dsa_pointer param_exec; /* serialized PARAM_EXEC parameters */
+ bool finished; /* set true by ExecParallelFinish */
+ /* These two arrays have pcxt->nworkers_launched entries: */
+ shm_mq_handle **tqueue; /* tuple queues for worker output */
+ struct TupleQueueReader **reader; /* tuple reader/writer support */
+} ParallelExecutorInfo;
+
+extern ParallelExecutorInfo *ExecInitParallelPlan(PlanState *planstate,
+ EState *estate, Bitmapset *sendParam, int nworkers,
+ int64 tuples_needed);
+extern void ExecParallelCreateReaders(ParallelExecutorInfo *pei);
+extern void ExecParallelFinish(ParallelExecutorInfo *pei);
+extern void ExecParallelCleanup(ParallelExecutorInfo *pei);
+extern void ExecParallelReinitialize(PlanState *planstate,
+ ParallelExecutorInfo *pei, Bitmapset *sendParam);
+
+extern void ParallelQueryMain(dsm_segment *seg, shm_toc *toc);
+
+#endif /* EXECPARALLEL_H */
diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h
new file mode 100644
index 0000000..694e38b
--- /dev/null
+++ b/src/include/executor/execPartition.h
@@ -0,0 +1,128 @@
+/*--------------------------------------------------------------------
+ * execPartition.h
+ * POSTGRES partitioning executor interface
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/executor/execPartition.h
+ *--------------------------------------------------------------------
+ */
+
+#ifndef EXECPARTITION_H
+#define EXECPARTITION_H
+
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
+#include "partitioning/partprune.h"
+
+/* See execPartition.c for the definitions. */
+typedef struct PartitionDispatchData *PartitionDispatch;
+typedef struct PartitionTupleRouting PartitionTupleRouting;
+
+/*
+ * PartitionedRelPruningData - Per-partitioned-table data for run-time pruning
+ * of partitions. For a multilevel partitioned table, we have one of these
+ * for the topmost partition plus one for each non-leaf child partition.
+ *
+ * subplan_map[] and subpart_map[] have the same definitions as in
+ * PartitionedRelPruneInfo (see plannodes.h); though note that here,
+ * subpart_map contains indexes into PartitionPruningData.partrelprunedata[].
+ *
+ * nparts Length of subplan_map[] and subpart_map[].
+ * subplan_map Subplan index by partition index, or -1.
+ * subpart_map Subpart index by partition index, or -1.
+ * present_parts A Bitmapset of the partition indexes that we
+ * have subplans or subparts for.
+ * initial_pruning_steps List of PartitionPruneSteps used to
+ * perform executor startup pruning.
+ * exec_pruning_steps List of PartitionPruneSteps used to
+ * perform per-scan pruning.
+ * initial_context If initial_pruning_steps isn't NIL, contains
+ * the details needed to execute those steps.
+ * exec_context If exec_pruning_steps isn't NIL, contains
+ * the details needed to execute those steps.
+ */
+typedef struct PartitionedRelPruningData
+{
+ int nparts;
+ int *subplan_map;
+ int *subpart_map;
+ Bitmapset *present_parts;
+ List *initial_pruning_steps;
+ List *exec_pruning_steps;
+ PartitionPruneContext initial_context;
+ PartitionPruneContext exec_context;
+} PartitionedRelPruningData;
+
+/*
+ * PartitionPruningData - Holds all the run-time pruning information for
+ * a single partitioning hierarchy containing one or more partitions.
+ * partrelprunedata[] is an array ordered such that parents appear before
+ * their children; in particular, the first entry is the topmost partition,
+ * which was actually named in the SQL query.
+ */
+typedef struct PartitionPruningData
+{
+ int num_partrelprunedata; /* number of array entries */
+ PartitionedRelPruningData partrelprunedata[FLEXIBLE_ARRAY_MEMBER];
+} PartitionPruningData;
+
+/*
+ * PartitionPruneState - State object required for plan nodes to perform
+ * run-time partition pruning.
+ *
+ * This struct can be attached to plan types which support arbitrary Lists of
+ * subplans containing partitions, to allow subplans to be eliminated due to
+ * the clauses being unable to match to any tuple that the subplan could
+ * possibly produce.
+ *
+ * execparamids Contains paramids of PARAM_EXEC Params found within
+ * any of the partprunedata structs. Pruning must be
+ * done again each time the value of one of these
+ * parameters changes.
+ * other_subplans Contains indexes of subplans that don't belong to any
+ * "partprunedata", e.g UNION ALL children that are not
+ * partitioned tables, or a partitioned table that the
+ * planner deemed run-time pruning to be useless for.
+ * These must not be pruned.
+ * prune_context A short-lived memory context in which to execute the
+ * partition pruning functions.
+ * do_initial_prune true if pruning should be performed during executor
+ * startup (at any hierarchy level).
+ * do_exec_prune true if pruning should be performed during
+ * executor run (at any hierarchy level).
+ * num_partprunedata Number of items in "partprunedata" array.
+ * partprunedata Array of PartitionPruningData pointers for the plan's
+ * partitioned relation(s), one for each partitioning
+ * hierarchy that requires run-time pruning.
+ */
+typedef struct PartitionPruneState
+{
+ Bitmapset *execparamids;
+ Bitmapset *other_subplans;
+ MemoryContext prune_context;
+ bool do_initial_prune;
+ bool do_exec_prune;
+ int num_partprunedata;
+ PartitionPruningData *partprunedata[FLEXIBLE_ARRAY_MEMBER];
+} PartitionPruneState;
+
+extern PartitionTupleRouting *ExecSetupPartitionTupleRouting(EState *estate,
+ Relation rel);
+extern ResultRelInfo *ExecFindPartition(ModifyTableState *mtstate,
+ ResultRelInfo *rootResultRelInfo,
+ PartitionTupleRouting *proute,
+ TupleTableSlot *slot,
+ EState *estate);
+extern void ExecCleanupTupleRouting(ModifyTableState *mtstate,
+ PartitionTupleRouting *proute);
+extern PartitionPruneState *ExecCreatePartitionPruneState(PlanState *planstate,
+ PartitionPruneInfo *partitionpruneinfo);
+extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate);
+extern Bitmapset *ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate,
+ int nsubplans);
+
+#endif /* EXECPARTITION_H */
diff --git a/src/include/executor/execdebug.h b/src/include/executor/execdebug.h
new file mode 100644
index 0000000..596c499
--- /dev/null
+++ b/src/include/executor/execdebug.h
@@ -0,0 +1,130 @@
+/*-------------------------------------------------------------------------
+ *
+ * execdebug.h
+ * #defines governing debugging behaviour in the executor
+ *
+ * XXX this is all pretty old and crufty. Newer code tends to use elog()
+ * for debug printouts, because that's more flexible than printf().
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/execdebug.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECDEBUG_H
+#define EXECDEBUG_H
+
+#include "executor/executor.h"
+#include "nodes/print.h"
+
+/* ----------------------------------------------------------------
+ * debugging defines.
+ *
+ * If you want certain debugging behaviour, then #define
+ * the variable to 1. No need to explicitly #undef by default,
+ * since we can use -D compiler options to enable features.
+ * - thomas 1999-02-20
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * EXEC_NESTLOOPDEBUG is a flag which turns on debugging of the
+ * nest loop node by NL_printf() and ENL_printf() in nodeNestloop.c
+ * ----------------
+#undef EXEC_NESTLOOPDEBUG
+ */
+
+/* ----------------
+ * EXEC_SORTDEBUG is a flag which turns on debugging of
+ * the ExecSort() stuff by SO_printf() in nodeSort.c
+ * ----------------
+#undef EXEC_SORTDEBUG
+ */
+
+/* ----------------
+ * EXEC_MERGEJOINDEBUG is a flag which turns on debugging of
+ * the ExecMergeJoin() stuff by MJ_printf() in nodeMergejoin.c
+ * ----------------
+#undef EXEC_MERGEJOINDEBUG
+ */
+
+/* ----------------------------------------------------------------
+ * #defines controlled by above definitions
+ *
+ * Note: most of these are "incomplete" because I didn't
+ * need the ones not defined. More should be added
+ * only as necessary -cim 10/26/89
+ * ----------------------------------------------------------------
+ */
+#define T_OR_F(b) ((b) ? "true" : "false")
+#define NULL_OR_TUPLE(slot) (TupIsNull(slot) ? "null" : "a tuple")
+
+/* ----------------
+ * nest loop debugging defines
+ * ----------------
+ */
+#ifdef EXEC_NESTLOOPDEBUG
+#define NL_nodeDisplay(l) nodeDisplay(l)
+#define NL_printf(s) printf(s)
+#define NL1_printf(s, a) printf(s, a)
+#define ENL1_printf(message) printf("ExecNestLoop: %s\n", message)
+#else
+#define NL_nodeDisplay(l)
+#define NL_printf(s)
+#define NL1_printf(s, a)
+#define ENL1_printf(message)
+#endif /* EXEC_NESTLOOPDEBUG */
+
+/* ----------------
+ * sort node debugging defines
+ * ----------------
+ */
+#ifdef EXEC_SORTDEBUG
+#define SO_nodeDisplay(l) nodeDisplay(l)
+#define SO_printf(s) printf(s)
+#define SO1_printf(s, p) printf(s, p)
+#define SO2_printf(s, p1, p2) printf(s, p1, p2)
+#else
+#define SO_nodeDisplay(l)
+#define SO_printf(s)
+#define SO1_printf(s, p)
+#define SO2_printf(s, p1, p2)
+#endif /* EXEC_SORTDEBUG */
+
+/* ----------------
+ * merge join debugging defines
+ * ----------------
+ */
+#ifdef EXEC_MERGEJOINDEBUG
+
+#define MJ_nodeDisplay(l) nodeDisplay(l)
+#define MJ_printf(s) printf(s)
+#define MJ1_printf(s, p) printf(s, p)
+#define MJ2_printf(s, p1, p2) printf(s, p1, p2)
+#define MJ_debugtup(slot) debugtup(slot, NULL)
+#define MJ_dump(state) ExecMergeTupleDump(state)
+#define MJ_DEBUG_COMPARE(res) \
+ MJ1_printf(" MJCompare() returns %d\n", (res))
+#define MJ_DEBUG_QUAL(clause, res) \
+ MJ2_printf(" ExecQual(%s, econtext) returns %s\n", \
+ CppAsString(clause), T_OR_F(res))
+#define MJ_DEBUG_PROC_NODE(slot) \
+ MJ2_printf(" %s = ExecProcNode(...) returns %s\n", \
+ CppAsString(slot), NULL_OR_TUPLE(slot))
+#else
+
+#define MJ_nodeDisplay(l)
+#define MJ_printf(s)
+#define MJ1_printf(s, p)
+#define MJ2_printf(s, p1, p2)
+#define MJ_debugtup(slot)
+#define MJ_dump(state)
+#define MJ_DEBUG_COMPARE(res)
+#define MJ_DEBUG_QUAL(clause, res)
+#define MJ_DEBUG_PROC_NODE(slot)
+#endif /* EXEC_MERGEJOINDEBUG */
+
+#endif /* EXECDEBUG_H */
diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h
new file mode 100644
index 0000000..017ad87
--- /dev/null
+++ b/src/include/executor/execdesc.h
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * execdesc.h
+ * plan and query descriptor accessor macros used by the executor
+ * and related modules.
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/execdesc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECDESC_H
+#define EXECDESC_H
+
+#include "nodes/execnodes.h"
+#include "tcop/dest.h"
+
+
+/* ----------------
+ * query descriptor:
+ *
+ * a QueryDesc encapsulates everything that the executor
+ * needs to execute the query.
+ *
+ * For the convenience of SQL-language functions, we also support QueryDescs
+ * containing utility statements; these must not be passed to the executor
+ * however.
+ * ---------------------
+ */
+typedef struct QueryDesc
+{
+ /* These fields are provided by CreateQueryDesc */
+ CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */
+ PlannedStmt *plannedstmt; /* planner's output (could be utility, too) */
+ const char *sourceText; /* source text of the query */
+ Snapshot snapshot; /* snapshot to use for query */
+ Snapshot crosscheck_snapshot; /* crosscheck for RI update/delete */
+ DestReceiver *dest; /* the destination for tuple output */
+ ParamListInfo params; /* param values being passed in */
+ QueryEnvironment *queryEnv; /* query environment passed in */
+ int instrument_options; /* OR of InstrumentOption flags */
+
+ /* These fields are set by ExecutorStart */
+ TupleDesc tupDesc; /* descriptor for result tuples */
+ EState *estate; /* executor's query-wide state */
+ PlanState *planstate; /* tree of per-plan-node state */
+
+ /* This field is set by ExecutorRun */
+ bool already_executed; /* true if previously executed */
+
+ /* This is always set NULL by the core system, but plugins can change it */
+ struct Instrumentation *totaltime; /* total time spent in ExecutorRun */
+} QueryDesc;
+
+/* in pquery.c */
+extern QueryDesc *CreateQueryDesc(PlannedStmt *plannedstmt,
+ const char *sourceText,
+ Snapshot snapshot,
+ Snapshot crosscheck_snapshot,
+ DestReceiver *dest,
+ ParamListInfo params,
+ QueryEnvironment *queryEnv,
+ int instrument_options);
+
+extern void FreeQueryDesc(QueryDesc *qdesc);
+
+#endif /* EXECDESC_H */
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
new file mode 100644
index 0000000..3dc03c9
--- /dev/null
+++ b/src/include/executor/executor.h
@@ -0,0 +1,661 @@
+/*-------------------------------------------------------------------------
+ *
+ * executor.h
+ * support for the POSTGRES executor module
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/executor.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECUTOR_H
+#define EXECUTOR_H
+
+#include "executor/execdesc.h"
+#include "fmgr.h"
+#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
+#include "utils/memutils.h"
+
+
+/*
+ * The "eflags" argument to ExecutorStart and the various ExecInitNode
+ * routines is a bitwise OR of the following flag bits, which tell the
+ * called plan node what to expect. Note that the flags will get modified
+ * as they are passed down the plan tree, since an upper node may require
+ * functionality in its subnode not demanded of the plan as a whole
+ * (example: MergeJoin requires mark/restore capability in its inner input),
+ * or an upper node may shield its input from some functionality requirement
+ * (example: Materialize shields its input from needing to do backward scan).
+ *
+ * EXPLAIN_ONLY indicates that the plan tree is being initialized just so
+ * EXPLAIN can print it out; it will not be run. Hence, no side-effects
+ * of startup should occur. However, error checks (such as permission checks)
+ * should be performed.
+ *
+ * REWIND indicates that the plan node should try to efficiently support
+ * rescans without parameter changes. (Nodes must support ExecReScan calls
+ * in any case, but if this flag was not given, they are at liberty to do it
+ * through complete recalculation. Note that a parameter change forces a
+ * full recalculation in any case.)
+ *
+ * BACKWARD indicates that the plan node must respect the es_direction flag.
+ * When this is not passed, the plan node will only be run forwards.
+ *
+ * MARK indicates that the plan node must support Mark/Restore calls.
+ * When this is not passed, no Mark/Restore will occur.
+ *
+ * SKIP_TRIGGERS tells ExecutorStart/ExecutorFinish to skip calling
+ * AfterTriggerBeginQuery/AfterTriggerEndQuery. This does not necessarily
+ * mean that the plan can't queue any AFTER triggers; just that the caller
+ * is responsible for there being a trigger context for them to be queued in.
+ */
+#define EXEC_FLAG_EXPLAIN_ONLY 0x0001 /* EXPLAIN, no ANALYZE */
+#define EXEC_FLAG_REWIND 0x0002 /* need efficient rescan */
+#define EXEC_FLAG_BACKWARD 0x0004 /* need backward scan */
+#define EXEC_FLAG_MARK 0x0008 /* need mark/restore */
+#define EXEC_FLAG_SKIP_TRIGGERS 0x0010 /* skip AfterTrigger calls */
+#define EXEC_FLAG_WITH_NO_DATA 0x0020 /* rel scannability doesn't matter */
+
+
+/* Hook for plugins to get control in ExecutorStart() */
+typedef void (*ExecutorStart_hook_type) (QueryDesc *queryDesc, int eflags);
+extern PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook;
+
+/* Hook for plugins to get control in ExecutorRun() */
+typedef void (*ExecutorRun_hook_type) (QueryDesc *queryDesc,
+ ScanDirection direction,
+ uint64 count,
+ bool execute_once);
+extern PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook;
+
+/* Hook for plugins to get control in ExecutorFinish() */
+typedef void (*ExecutorFinish_hook_type) (QueryDesc *queryDesc);
+extern PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook;
+
+/* Hook for plugins to get control in ExecutorEnd() */
+typedef void (*ExecutorEnd_hook_type) (QueryDesc *queryDesc);
+extern PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook;
+
+/* Hook for plugins to get control in ExecCheckRTPerms() */
+typedef bool (*ExecutorCheckPerms_hook_type) (List *, bool);
+extern PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook;
+
+
+/*
+ * prototypes from functions in execAmi.c
+ */
+struct Path; /* avoid including pathnodes.h here */
+
+extern void ExecReScan(PlanState *node);
+extern void ExecMarkPos(PlanState *node);
+extern void ExecRestrPos(PlanState *node);
+extern bool ExecSupportsMarkRestore(struct Path *pathnode);
+extern bool ExecSupportsBackwardScan(Plan *node);
+extern bool ExecMaterializesOutput(NodeTag plantype);
+
+/*
+ * prototypes from functions in execCurrent.c
+ */
+extern bool execCurrentOf(CurrentOfExpr *cexpr,
+ ExprContext *econtext,
+ Oid table_oid,
+ ItemPointer current_tid);
+
+/*
+ * prototypes from functions in execGrouping.c
+ */
+extern ExprState *execTuplesMatchPrepare(TupleDesc desc,
+ int numCols,
+ const AttrNumber *keyColIdx,
+ const Oid *eqOperators,
+ const Oid *collations,
+ PlanState *parent);
+extern void execTuplesHashPrepare(int numCols,
+ const Oid *eqOperators,
+ Oid **eqFuncOids,
+ FmgrInfo **hashFunctions);
+extern TupleHashTable BuildTupleHashTable(PlanState *parent,
+ TupleDesc inputDesc,
+ int numCols, AttrNumber *keyColIdx,
+ const Oid *eqfuncoids,
+ FmgrInfo *hashfunctions,
+ Oid *collations,
+ long nbuckets, Size additionalsize,
+ MemoryContext tablecxt,
+ MemoryContext tempcxt, bool use_variable_hash_iv);
+extern TupleHashTable BuildTupleHashTableExt(PlanState *parent,
+ TupleDesc inputDesc,
+ int numCols, AttrNumber *keyColIdx,
+ const Oid *eqfuncoids,
+ FmgrInfo *hashfunctions,
+ Oid *collations,
+ long nbuckets, Size additionalsize,
+ MemoryContext metacxt,
+ MemoryContext tablecxt,
+ MemoryContext tempcxt, bool use_variable_hash_iv);
+extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable,
+ TupleTableSlot *slot,
+ bool *isnew, uint32 *hash);
+extern uint32 TupleHashTableHash(TupleHashTable hashtable,
+ TupleTableSlot *slot);
+extern TupleHashEntry LookupTupleHashEntryHash(TupleHashTable hashtable,
+ TupleTableSlot *slot,
+ bool *isnew, uint32 hash);
+extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable,
+ TupleTableSlot *slot,
+ ExprState *eqcomp,
+ FmgrInfo *hashfunctions);
+extern void ResetTupleHashTable(TupleHashTable hashtable);
+
+/*
+ * prototypes from functions in execJunk.c
+ */
+extern JunkFilter *ExecInitJunkFilter(List *targetList,
+ TupleTableSlot *slot);
+extern JunkFilter *ExecInitJunkFilterConversion(List *targetList,
+ TupleDesc cleanTupType,
+ TupleTableSlot *slot);
+extern AttrNumber ExecFindJunkAttribute(JunkFilter *junkfilter,
+ const char *attrName);
+extern AttrNumber ExecFindJunkAttributeInTlist(List *targetlist,
+ const char *attrName);
+extern TupleTableSlot *ExecFilterJunk(JunkFilter *junkfilter,
+ TupleTableSlot *slot);
+
+/*
+ * ExecGetJunkAttribute
+ *
+ * Given a junk filter's input tuple (slot) and a junk attribute's number
+ * previously found by ExecFindJunkAttribute, extract & return the value and
+ * isNull flag of the attribute.
+ */
+#ifndef FRONTEND
+static inline Datum
+ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
+{
+ Assert(attno > 0);
+ return slot_getattr(slot, attno, isNull);
+}
+#endif
+
+/*
+ * prototypes from functions in execMain.c
+ */
+extern void ExecutorStart(QueryDesc *queryDesc, int eflags);
+extern void standard_ExecutorStart(QueryDesc *queryDesc, int eflags);
+extern void ExecutorRun(QueryDesc *queryDesc,
+ ScanDirection direction, uint64 count, bool execute_once);
+extern void standard_ExecutorRun(QueryDesc *queryDesc,
+ ScanDirection direction, uint64 count, bool execute_once);
+extern void ExecutorFinish(QueryDesc *queryDesc);
+extern void standard_ExecutorFinish(QueryDesc *queryDesc);
+extern void ExecutorEnd(QueryDesc *queryDesc);
+extern void standard_ExecutorEnd(QueryDesc *queryDesc);
+extern void ExecutorRewind(QueryDesc *queryDesc);
+extern bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation);
+extern void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation);
+extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
+ Relation resultRelationDesc,
+ Index resultRelationIndex,
+ ResultRelInfo *partition_root_rri,
+ int instrument_options);
+extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
+extern void ExecConstraints(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate);
+extern bool ExecPartitionCheck(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate, bool emitError);
+extern void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate);
+extern void ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate);
+extern LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo);
+extern ExecRowMark *ExecFindRowMark(EState *estate, Index rti, bool missing_ok);
+extern ExecAuxRowMark *ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist);
+extern TupleTableSlot *EvalPlanQual(EPQState *epqstate, Relation relation,
+ Index rti, TupleTableSlot *testslot);
+extern void EvalPlanQualInit(EPQState *epqstate, EState *parentestate,
+ Plan *subplan, List *auxrowmarks, int epqParam);
+extern void EvalPlanQualSetPlan(EPQState *epqstate,
+ Plan *subplan, List *auxrowmarks);
+extern TupleTableSlot *EvalPlanQualSlot(EPQState *epqstate,
+ Relation relation, Index rti);
+
+#define EvalPlanQualSetSlot(epqstate, slot) ((epqstate)->origslot = (slot))
+extern bool EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot);
+extern TupleTableSlot *EvalPlanQualNext(EPQState *epqstate);
+extern void EvalPlanQualBegin(EPQState *epqstate);
+extern void EvalPlanQualEnd(EPQState *epqstate);
+
+/*
+ * functions in execProcnode.c
+ */
+extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags);
+extern void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function);
+extern Node *MultiExecProcNode(PlanState *node);
+extern void ExecEndNode(PlanState *node);
+extern bool ExecShutdownNode(PlanState *node);
+extern void ExecSetTupleBound(int64 tuples_needed, PlanState *child_node);
+
+
+/* ----------------------------------------------------------------
+ * ExecProcNode
+ *
+ * Execute the given node to return a(nother) tuple.
+ * ----------------------------------------------------------------
+ */
+#ifndef FRONTEND
+static inline TupleTableSlot *
+ExecProcNode(PlanState *node)
+{
+ if (node->chgParam != NULL) /* something changed? */
+ ExecReScan(node); /* let ReScan handle this */
+
+ return node->ExecProcNode(node);
+}
+#endif
+
+/*
+ * prototypes from functions in execExpr.c
+ */
+extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
+extern ExprState *ExecInitExprWithParams(Expr *node, ParamListInfo ext_params);
+extern ExprState *ExecInitQual(List *qual, PlanState *parent);
+extern ExprState *ExecInitCheck(List *qual, PlanState *parent);
+extern List *ExecInitExprList(List *nodes, PlanState *parent);
+extern ExprState *ExecBuildAggTrans(AggState *aggstate, struct AggStatePerPhaseData *phase,
+ bool doSort, bool doHash, bool nullcheck);
+extern ExprState *ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
+ const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
+ int numCols,
+ const AttrNumber *keyColIdx,
+ const Oid *eqfunctions,
+ const Oid *collations,
+ PlanState *parent);
+extern ExprState *ExecBuildParamSetEqual(TupleDesc desc,
+ const TupleTableSlotOps *lops,
+ const TupleTableSlotOps *rops,
+ const Oid *eqfunctions,
+ const Oid *collations,
+ const List *param_exprs,
+ PlanState *parent);
+extern ProjectionInfo *ExecBuildProjectionInfo(List *targetList,
+ ExprContext *econtext,
+ TupleTableSlot *slot,
+ PlanState *parent,
+ TupleDesc inputDesc);
+extern ProjectionInfo *ExecBuildUpdateProjection(List *targetList,
+ bool evalTargetList,
+ List *targetColnos,
+ TupleDesc relDesc,
+ ExprContext *econtext,
+ TupleTableSlot *slot,
+ PlanState *parent);
+extern ExprState *ExecPrepareExpr(Expr *node, EState *estate);
+extern ExprState *ExecPrepareQual(List *qual, EState *estate);
+extern ExprState *ExecPrepareCheck(List *qual, EState *estate);
+extern List *ExecPrepareExprList(List *nodes, EState *estate);
+
+/*
+ * ExecEvalExpr
+ *
+ * Evaluate expression identified by "state" in the execution context
+ * given by "econtext". *isNull is set to the is-null flag for the result,
+ * and the Datum value is the function result.
+ *
+ * The caller should already have switched into the temporary memory
+ * context econtext->ecxt_per_tuple_memory. The convenience entry point
+ * ExecEvalExprSwitchContext() is provided for callers who don't prefer to
+ * do the switch in an outer loop.
+ */
+#ifndef FRONTEND
+static inline Datum
+ExecEvalExpr(ExprState *state,
+ ExprContext *econtext,
+ bool *isNull)
+{
+ return state->evalfunc(state, econtext, isNull);
+}
+#endif
+
+/*
+ * ExecEvalExprSwitchContext
+ *
+ * Same as ExecEvalExpr, but get into the right allocation context explicitly.
+ */
+#ifndef FRONTEND
+static inline Datum
+ExecEvalExprSwitchContext(ExprState *state,
+ ExprContext *econtext,
+ bool *isNull)
+{
+ Datum retDatum;
+ MemoryContext oldContext;
+
+ oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+ retDatum = state->evalfunc(state, econtext, isNull);
+ MemoryContextSwitchTo(oldContext);
+ return retDatum;
+}
+#endif
+
+/*
+ * ExecProject
+ *
+ * Projects a tuple based on projection info and stores it in the slot passed
+ * to ExecBuildProjectionInfo().
+ *
+ * Note: the result is always a virtual tuple; therefore it may reference
+ * the contents of the exprContext's scan tuples and/or temporary results
+ * constructed in the exprContext. If the caller wishes the result to be
+ * valid longer than that data will be valid, he must call ExecMaterializeSlot
+ * on the result slot.
+ */
+#ifndef FRONTEND
+static inline TupleTableSlot *
+ExecProject(ProjectionInfo *projInfo)
+{
+ ExprContext *econtext = projInfo->pi_exprContext;
+ ExprState *state = &projInfo->pi_state;
+ TupleTableSlot *slot = state->resultslot;
+ bool isnull;
+
+ /*
+ * Clear any former contents of the result slot. This makes it safe for
+ * us to use the slot's Datum/isnull arrays as workspace.
+ */
+ ExecClearTuple(slot);
+
+ /* Run the expression, discarding scalar result from the last column. */
+ (void) ExecEvalExprSwitchContext(state, econtext, &isnull);
+
+ /*
+ * Successfully formed a result row. Mark the result slot as containing a
+ * valid virtual tuple (inlined version of ExecStoreVirtualTuple()).
+ */
+ slot->tts_flags &= ~TTS_FLAG_EMPTY;
+ slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
+
+ return slot;
+}
+#endif
+
+/*
+ * ExecQual - evaluate a qual prepared with ExecInitQual (possibly via
+ * ExecPrepareQual). Returns true if qual is satisfied, else false.
+ *
+ * Note: ExecQual used to have a third argument "resultForNull". The
+ * behavior of this function now corresponds to resultForNull == false.
+ * If you want the resultForNull == true behavior, see ExecCheck.
+ */
+#ifndef FRONTEND
+static inline bool
+ExecQual(ExprState *state, ExprContext *econtext)
+{
+ Datum ret;
+ bool isnull;
+
+ /* short-circuit (here and in ExecInitQual) for empty restriction list */
+ if (state == NULL)
+ return true;
+
+ /* verify that expression was compiled using ExecInitQual */
+ Assert(state->flags & EEO_FLAG_IS_QUAL);
+
+ ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
+
+ /* EEOP_QUAL should never return NULL */
+ Assert(!isnull);
+
+ return DatumGetBool(ret);
+}
+#endif
+
+/*
+ * ExecQualAndReset() - evaluate qual with ExecQual() and reset expression
+ * context.
+ */
+#ifndef FRONTEND
+static inline bool
+ExecQualAndReset(ExprState *state, ExprContext *econtext)
+{
+ bool ret = ExecQual(state, econtext);
+
+ /* inline ResetExprContext, to avoid ordering issue in this file */
+ MemoryContextReset(econtext->ecxt_per_tuple_memory);
+ return ret;
+}
+#endif
+
+extern bool ExecCheck(ExprState *state, ExprContext *context);
+
+/*
+ * prototypes from functions in execSRF.c
+ */
+extern SetExprState *ExecInitTableFunctionResult(Expr *expr,
+ ExprContext *econtext, PlanState *parent);
+extern Tuplestorestate *ExecMakeTableFunctionResult(SetExprState *setexpr,
+ ExprContext *econtext,
+ MemoryContext argContext,
+ TupleDesc expectedDesc,
+ bool randomAccess);
+extern SetExprState *ExecInitFunctionResultSet(Expr *expr,
+ ExprContext *econtext, PlanState *parent);
+extern Datum ExecMakeFunctionResultSet(SetExprState *fcache,
+ ExprContext *econtext,
+ MemoryContext argContext,
+ bool *isNull,
+ ExprDoneCond *isDone);
+
+/*
+ * prototypes from functions in execScan.c
+ */
+typedef TupleTableSlot *(*ExecScanAccessMtd) (ScanState *node);
+typedef bool (*ExecScanRecheckMtd) (ScanState *node, TupleTableSlot *slot);
+
+extern TupleTableSlot *ExecScan(ScanState *node, ExecScanAccessMtd accessMtd,
+ ExecScanRecheckMtd recheckMtd);
+extern void ExecAssignScanProjectionInfo(ScanState *node);
+extern void ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno);
+extern void ExecScanReScan(ScanState *node);
+
+/*
+ * prototypes from functions in execTuples.c
+ */
+extern void ExecInitResultTypeTL(PlanState *planstate);
+extern void ExecInitResultSlot(PlanState *planstate,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecInitResultTupleSlotTL(PlanState *planstate,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate,
+ TupleDesc tupleDesc,
+ const TupleTableSlotOps *tts_ops);
+extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
+ TupleDesc tupledesc,
+ const TupleTableSlotOps *tts_ops);
+extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType,
+ const TupleTableSlotOps *tts_ops);
+extern TupleDesc ExecTypeFromTL(List *targetList);
+extern TupleDesc ExecCleanTypeFromTL(List *targetList);
+extern TupleDesc ExecTypeFromExprList(List *exprList);
+extern void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList);
+extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg);
+
+typedef struct TupOutputState
+{
+ TupleTableSlot *slot;
+ DestReceiver *dest;
+} TupOutputState;
+
+extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest,
+ TupleDesc tupdesc,
+ const TupleTableSlotOps *tts_ops);
+extern void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull);
+extern void do_text_output_multiline(TupOutputState *tstate, const char *txt);
+extern void end_tup_output(TupOutputState *tstate);
+
+/*
+ * Write a single line of text given as a C string.
+ *
+ * Should only be used with a single-TEXT-attribute tupdesc.
+ */
+#define do_text_output_oneline(tstate, str_to_emit) \
+ do { \
+ Datum values_[1]; \
+ bool isnull_[1]; \
+ values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
+ isnull_[0] = false; \
+ do_tup_output(tstate, values_, isnull_); \
+ pfree(DatumGetPointer(values_[0])); \
+ } while (0)
+
+
+/*
+ * prototypes from functions in execUtils.c
+ */
+extern EState *CreateExecutorState(void);
+extern void FreeExecutorState(EState *estate);
+extern ExprContext *CreateExprContext(EState *estate);
+extern ExprContext *CreateWorkExprContext(EState *estate);
+extern ExprContext *CreateStandaloneExprContext(void);
+extern void FreeExprContext(ExprContext *econtext, bool isCommit);
+extern void ReScanExprContext(ExprContext *econtext);
+
+#define ResetExprContext(econtext) \
+ MemoryContextReset((econtext)->ecxt_per_tuple_memory)
+
+extern ExprContext *MakePerTupleExprContext(EState *estate);
+
+/* Get an EState's per-output-tuple exprcontext, making it if first use */
+#define GetPerTupleExprContext(estate) \
+ ((estate)->es_per_tuple_exprcontext ? \
+ (estate)->es_per_tuple_exprcontext : \
+ MakePerTupleExprContext(estate))
+
+#define GetPerTupleMemoryContext(estate) \
+ (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
+
+/* Reset an EState's per-output-tuple exprcontext, if one's been created */
+#define ResetPerTupleExprContext(estate) \
+ do { \
+ if ((estate)->es_per_tuple_exprcontext) \
+ ResetExprContext((estate)->es_per_tuple_exprcontext); \
+ } while (0)
+
+extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
+extern TupleDesc ExecGetResultType(PlanState *planstate);
+extern const TupleTableSlotOps *ExecGetResultSlotOps(PlanState *planstate,
+ bool *isfixed);
+extern void ExecAssignProjectionInfo(PlanState *planstate,
+ TupleDesc inputDesc);
+extern void ExecConditionalAssignProjectionInfo(PlanState *planstate,
+ TupleDesc inputDesc, Index varno);
+extern void ExecFreeExprContext(PlanState *planstate);
+extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc);
+extern void ExecCreateScanSlotFromOuterPlan(EState *estate,
+ ScanState *scanstate,
+ const TupleTableSlotOps *tts_ops);
+
+extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
+
+extern Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags);
+
+extern void ExecInitRangeTable(EState *estate, List *rangeTable);
+extern void ExecCloseRangeTableRelations(EState *estate);
+extern void ExecCloseResultRelations(EState *estate);
+
+static inline RangeTblEntry *
+exec_rt_fetch(Index rti, EState *estate)
+{
+ return (RangeTblEntry *) list_nth(estate->es_range_table, rti - 1);
+}
+
+extern Relation ExecGetRangeTableRelation(EState *estate, Index rti);
+extern void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
+ Index rti);
+
+extern int executor_errposition(EState *estate, int location);
+
+extern void RegisterExprContextCallback(ExprContext *econtext,
+ ExprContextCallbackFunction function,
+ Datum arg);
+extern void UnregisterExprContextCallback(ExprContext *econtext,
+ ExprContextCallbackFunction function,
+ Datum arg);
+
+extern Datum GetAttributeByName(HeapTupleHeader tuple, const char *attname,
+ bool *isNull);
+extern Datum GetAttributeByNum(HeapTupleHeader tuple, AttrNumber attrno,
+ bool *isNull);
+
+extern int ExecTargetListLength(List *targetlist);
+extern int ExecCleanTargetListLength(List *targetlist);
+
+extern TupleTableSlot *ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo);
+extern TupleTableSlot *ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo);
+extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo);
+extern TupleConversionMap *ExecGetChildToRootMap(ResultRelInfo *resultRelInfo);
+
+extern Bitmapset *ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate);
+extern Bitmapset *ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate);
+extern Bitmapset *ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate);
+extern Bitmapset *ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate);
+
+/*
+ * prototypes from functions in execIndexing.c
+ */
+extern void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative);
+extern void ExecCloseIndices(ResultRelInfo *resultRelInfo);
+extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate,
+ bool update,
+ bool noDupErr,
+ bool *specConflict, List *arbiterIndexes);
+extern bool ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot,
+ EState *estate, ItemPointer conflictTid,
+ List *arbiterIndexes);
+extern void check_exclusion_constraint(Relation heap, Relation index,
+ IndexInfo *indexInfo,
+ ItemPointer tupleid,
+ Datum *values, bool *isnull,
+ EState *estate, bool newIndex);
+
+/*
+ * prototypes from functions in execReplication.c
+ */
+extern bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid,
+ LockTupleMode lockmode,
+ TupleTableSlot *searchslot,
+ TupleTableSlot *outslot);
+extern bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
+ TupleTableSlot *searchslot, TupleTableSlot *outslot);
+
+extern void ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo,
+ EState *estate, TupleTableSlot *slot);
+extern void ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo,
+ EState *estate, EPQState *epqstate,
+ TupleTableSlot *searchslot, TupleTableSlot *slot);
+extern void ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo,
+ EState *estate, EPQState *epqstate,
+ TupleTableSlot *searchslot);
+extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd);
+
+extern void CheckSubscriptionRelkind(char relkind, const char *nspname,
+ const char *relname);
+
+/*
+ * prototypes from functions in nodeModifyTable.c
+ */
+extern TupleTableSlot *ExecGetUpdateNewTuple(ResultRelInfo *relinfo,
+ TupleTableSlot *planSlot,
+ TupleTableSlot *oldSlot);
+extern ResultRelInfo *ExecLookupResultRelByOid(ModifyTableState *node,
+ Oid resultoid,
+ bool missing_ok,
+ bool update_cache);
+
+#endif /* EXECUTOR_H */
diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h
new file mode 100644
index 0000000..a9e14e2
--- /dev/null
+++ b/src/include/executor/functions.h
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * functions.h
+ * Declarations for execution of SQL-language functions.
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/functions.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FUNCTIONS_H
+#define FUNCTIONS_H
+
+#include "nodes/execnodes.h"
+#include "tcop/dest.h"
+
+/*
+ * Data structure needed by the parser callback hooks to resolve parameter
+ * references during parsing of a SQL function's body. This is separate from
+ * SQLFunctionCache since we sometimes do parsing separately from execution.
+ */
+typedef struct SQLFunctionParseInfo
+{
+ char *fname; /* function's name */
+ int nargs; /* number of input arguments */
+ Oid *argtypes; /* resolved types of input arguments */
+ char **argnames; /* names of input arguments; NULL if none */
+ /* Note that argnames[i] can be NULL, if some args are unnamed */
+ Oid collation; /* function's input collation, if known */
+} SQLFunctionParseInfo;
+
+typedef SQLFunctionParseInfo *SQLFunctionParseInfoPtr;
+
+extern Datum fmgr_sql(PG_FUNCTION_ARGS);
+
+extern SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple,
+ Node *call_expr,
+ Oid inputCollation);
+
+extern void sql_fn_parser_setup(struct ParseState *pstate,
+ SQLFunctionParseInfoPtr pinfo);
+
+extern void check_sql_fn_statements(List *queryTreeLists);
+
+extern bool check_sql_fn_retval(List *queryTreeLists,
+ Oid rettype, TupleDesc rettupdesc,
+ bool insertDroppedCols,
+ List **resultTargetList);
+
+extern DestReceiver *CreateSQLFunctionDestReceiver(void);
+
+#endif /* FUNCTIONS_H */
diff --git a/src/include/executor/hashjoin.h b/src/include/executor/hashjoin.h
new file mode 100644
index 0000000..d74034f
--- /dev/null
+++ b/src/include/executor/hashjoin.h
@@ -0,0 +1,362 @@
+/*-------------------------------------------------------------------------
+ *
+ * hashjoin.h
+ * internal structures for hash joins
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/hashjoin.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HASHJOIN_H
+#define HASHJOIN_H
+
+#include "nodes/execnodes.h"
+#include "port/atomics.h"
+#include "storage/barrier.h"
+#include "storage/buffile.h"
+#include "storage/lwlock.h"
+
+/* ----------------------------------------------------------------
+ * hash-join hash table structures
+ *
+ * Each active hashjoin has a HashJoinTable control block, which is
+ * palloc'd in the executor's per-query context. All other storage needed
+ * for the hashjoin is kept in private memory contexts, two for each hashjoin.
+ * This makes it easy and fast to release the storage when we don't need it
+ * anymore. (Exception: data associated with the temp files lives in the
+ * per-query context too, since we always call buffile.c in that context.)
+ *
+ * The hashtable contexts are made children of the per-query context, ensuring
+ * that they will be discarded at end of statement even if the join is
+ * aborted early by an error. (Likewise, any temporary files we make will
+ * be cleaned up by the virtual file manager in event of an error.)
+ *
+ * Storage that should live through the entire join is allocated from the
+ * "hashCxt", while storage that is only wanted for the current batch is
+ * allocated in the "batchCxt". By resetting the batchCxt at the end of
+ * each batch, we free all the per-batch storage reliably and without tedium.
+ *
+ * During first scan of inner relation, we get its tuples from executor.
+ * If nbatch > 1 then tuples that don't belong in first batch get saved
+ * into inner-batch temp files. The same statements apply for the
+ * first scan of the outer relation, except we write tuples to outer-batch
+ * temp files. After finishing the first scan, we do the following for
+ * each remaining batch:
+ * 1. Read tuples from inner batch file, load into hash buckets.
+ * 2. Read tuples from outer batch file, match to hash buckets and output.
+ *
+ * It is possible to increase nbatch on the fly if the in-memory hash table
+ * gets too big. The hash-value-to-batch computation is arranged so that this
+ * can only cause a tuple to go into a later batch than previously thought,
+ * never into an earlier batch. When we increase nbatch, we rescan the hash
+ * table and dump out any tuples that are now of a later batch to the correct
+ * inner batch file. Subsequently, while reading either inner or outer batch
+ * files, we might find tuples that no longer belong to the current batch;
+ * if so, we just dump them out to the correct batch file.
+ * ----------------------------------------------------------------
+ */
+
+/* these are in nodes/execnodes.h: */
+/* typedef struct HashJoinTupleData *HashJoinTuple; */
+/* typedef struct HashJoinTableData *HashJoinTable; */
+
+typedef struct HashJoinTupleData
+{
+ /* link to next tuple in same bucket */
+ union
+ {
+ struct HashJoinTupleData *unshared;
+ dsa_pointer shared;
+ } next;
+ uint32 hashvalue; /* tuple's hash code */
+ /* Tuple data, in MinimalTuple format, follows on a MAXALIGN boundary */
+} HashJoinTupleData;
+
+#define HJTUPLE_OVERHEAD MAXALIGN(sizeof(HashJoinTupleData))
+#define HJTUPLE_MINTUPLE(hjtup) \
+ ((MinimalTuple) ((char *) (hjtup) + HJTUPLE_OVERHEAD))
+
+/*
+ * If the outer relation's distribution is sufficiently nonuniform, we attempt
+ * to optimize the join by treating the hash values corresponding to the outer
+ * relation's MCVs specially. Inner relation tuples matching these hash
+ * values go into the "skew" hashtable instead of the main hashtable, and
+ * outer relation tuples with these hash values are matched against that
+ * table instead of the main one. Thus, tuples with these hash values are
+ * effectively handled as part of the first batch and will never go to disk.
+ * The skew hashtable is limited to SKEW_HASH_MEM_PERCENT of the total memory
+ * allowed for the join; while building the hashtables, we decrease the number
+ * of MCVs being specially treated if needed to stay under this limit.
+ *
+ * Note: you might wonder why we look at the outer relation stats for this,
+ * rather than the inner. One reason is that the outer relation is typically
+ * bigger, so we get more I/O savings by optimizing for its most common values.
+ * Also, for similarly-sized relations, the planner prefers to put the more
+ * uniformly distributed relation on the inside, so we're more likely to find
+ * interesting skew in the outer relation.
+ */
+typedef struct HashSkewBucket
+{
+ uint32 hashvalue; /* common hash value */
+ HashJoinTuple tuples; /* linked list of inner-relation tuples */
+} HashSkewBucket;
+
+#define SKEW_BUCKET_OVERHEAD MAXALIGN(sizeof(HashSkewBucket))
+#define INVALID_SKEW_BUCKET_NO (-1)
+#define SKEW_HASH_MEM_PERCENT 2
+#define SKEW_MIN_OUTER_FRACTION 0.01
+
+/*
+ * To reduce palloc overhead, the HashJoinTuples for the current batch are
+ * packed in 32kB buffers instead of pallocing each tuple individually.
+ */
+typedef struct HashMemoryChunkData
+{
+ int ntuples; /* number of tuples stored in this chunk */
+ size_t maxlen; /* size of the chunk's tuple buffer */
+ size_t used; /* number of buffer bytes already used */
+
+ /* pointer to the next chunk (linked list) */
+ union
+ {
+ struct HashMemoryChunkData *unshared;
+ dsa_pointer shared;
+ } next;
+
+ /*
+ * The chunk's tuple buffer starts after the HashMemoryChunkData struct,
+ * at offset HASH_CHUNK_HEADER_SIZE (which must be maxaligned). Note that
+ * that offset is not included in "maxlen" or "used".
+ */
+} HashMemoryChunkData;
+
+typedef struct HashMemoryChunkData *HashMemoryChunk;
+
+#define HASH_CHUNK_SIZE (32 * 1024L)
+#define HASH_CHUNK_HEADER_SIZE MAXALIGN(sizeof(HashMemoryChunkData))
+#define HASH_CHUNK_DATA(hc) (((char *) (hc)) + HASH_CHUNK_HEADER_SIZE)
+/* tuples exceeding HASH_CHUNK_THRESHOLD bytes are put in their own chunk */
+#define HASH_CHUNK_THRESHOLD (HASH_CHUNK_SIZE / 4)
+
+/*
+ * For each batch of a Parallel Hash Join, we have a ParallelHashJoinBatch
+ * object in shared memory to coordinate access to it. Since they are
+ * followed by variable-sized objects, they are arranged in contiguous memory
+ * but not accessed directly as an array.
+ */
+typedef struct ParallelHashJoinBatch
+{
+ dsa_pointer buckets; /* array of hash table buckets */
+ Barrier batch_barrier; /* synchronization for joining this batch */
+
+ dsa_pointer chunks; /* chunks of tuples loaded */
+ size_t size; /* size of buckets + chunks in memory */
+ size_t estimated_size; /* size of buckets + chunks while writing */
+ size_t ntuples; /* number of tuples loaded */
+ size_t old_ntuples; /* number of tuples before repartitioning */
+ bool space_exhausted;
+
+ /*
+ * Variable-sized SharedTuplestore objects follow this struct in memory.
+ * See the accessor macros below.
+ */
+} ParallelHashJoinBatch;
+
+/* Accessor for inner batch tuplestore following a ParallelHashJoinBatch. */
+#define ParallelHashJoinBatchInner(batch) \
+ ((SharedTuplestore *) \
+ ((char *) (batch) + MAXALIGN(sizeof(ParallelHashJoinBatch))))
+
+/* Accessor for outer batch tuplestore following a ParallelHashJoinBatch. */
+#define ParallelHashJoinBatchOuter(batch, nparticipants) \
+ ((SharedTuplestore *) \
+ ((char *) ParallelHashJoinBatchInner(batch) + \
+ MAXALIGN(sts_estimate(nparticipants))))
+
+/* Total size of a ParallelHashJoinBatch and tuplestores. */
+#define EstimateParallelHashJoinBatch(hashtable) \
+ (MAXALIGN(sizeof(ParallelHashJoinBatch)) + \
+ MAXALIGN(sts_estimate((hashtable)->parallel_state->nparticipants)) * 2)
+
+/* Accessor for the nth ParallelHashJoinBatch given the base. */
+#define NthParallelHashJoinBatch(base, n) \
+ ((ParallelHashJoinBatch *) \
+ ((char *) (base) + \
+ EstimateParallelHashJoinBatch(hashtable) * (n)))
+
+/*
+ * Each backend requires a small amount of per-batch state to interact with
+ * each ParallelHashJoinBatch.
+ */
+typedef struct ParallelHashJoinBatchAccessor
+{
+ ParallelHashJoinBatch *shared; /* pointer to shared state */
+
+ /* Per-backend partial counters to reduce contention. */
+ size_t preallocated; /* pre-allocated space for this backend */
+ size_t ntuples; /* number of tuples */
+ size_t size; /* size of partition in memory */
+ size_t estimated_size; /* size of partition on disk */
+ size_t old_ntuples; /* how many tuples before repartitioning? */
+ bool at_least_one_chunk; /* has this backend allocated a chunk? */
+
+ bool done; /* flag to remember that a batch is done */
+ SharedTuplestoreAccessor *inner_tuples;
+ SharedTuplestoreAccessor *outer_tuples;
+} ParallelHashJoinBatchAccessor;
+
+/*
+ * While hashing the inner relation, any participant might determine that it's
+ * time to increase the number of buckets to reduce the load factor or batches
+ * to reduce the memory size. This is indicated by setting the growth flag to
+ * these values.
+ */
+typedef enum ParallelHashGrowth
+{
+ /* The current dimensions are sufficient. */
+ PHJ_GROWTH_OK,
+ /* The load factor is too high, so we need to add buckets. */
+ PHJ_GROWTH_NEED_MORE_BUCKETS,
+ /* The memory budget would be exhausted, so we need to repartition. */
+ PHJ_GROWTH_NEED_MORE_BATCHES,
+ /* Repartitioning didn't help last time, so don't try to do that again. */
+ PHJ_GROWTH_DISABLED
+} ParallelHashGrowth;
+
+/*
+ * The shared state used to coordinate a Parallel Hash Join. This is stored
+ * in the DSM segment.
+ */
+typedef struct ParallelHashJoinState
+{
+ dsa_pointer batches; /* array of ParallelHashJoinBatch */
+ dsa_pointer old_batches; /* previous generation during repartition */
+ int nbatch; /* number of batches now */
+ int old_nbatch; /* previous number of batches */
+ int nbuckets; /* number of buckets */
+ ParallelHashGrowth growth; /* control batch/bucket growth */
+ dsa_pointer chunk_work_queue; /* chunk work queue */
+ int nparticipants;
+ size_t space_allowed;
+ size_t total_tuples; /* total number of inner tuples */
+ LWLock lock; /* lock protecting the above */
+
+ Barrier build_barrier; /* synchronization for the build phases */
+ Barrier grow_batches_barrier;
+ Barrier grow_buckets_barrier;
+ pg_atomic_uint32 distributor; /* counter for load balancing */
+
+ SharedFileSet fileset; /* space for shared temporary files */
+} ParallelHashJoinState;
+
+/* The phases for building batches, used by build_barrier. */
+#define PHJ_BUILD_ELECTING 0
+#define PHJ_BUILD_ALLOCATING 1
+#define PHJ_BUILD_HASHING_INNER 2
+#define PHJ_BUILD_HASHING_OUTER 3
+#define PHJ_BUILD_DONE 4
+
+/* The phases for probing each batch, used by for batch_barrier. */
+#define PHJ_BATCH_ELECTING 0
+#define PHJ_BATCH_ALLOCATING 1
+#define PHJ_BATCH_LOADING 2
+#define PHJ_BATCH_PROBING 3
+#define PHJ_BATCH_DONE 4
+
+/* The phases of batch growth while hashing, for grow_batches_barrier. */
+#define PHJ_GROW_BATCHES_ELECTING 0
+#define PHJ_GROW_BATCHES_ALLOCATING 1
+#define PHJ_GROW_BATCHES_REPARTITIONING 2
+#define PHJ_GROW_BATCHES_DECIDING 3
+#define PHJ_GROW_BATCHES_FINISHING 4
+#define PHJ_GROW_BATCHES_PHASE(n) ((n) % 5) /* circular phases */
+
+/* The phases of bucket growth while hashing, for grow_buckets_barrier. */
+#define PHJ_GROW_BUCKETS_ELECTING 0
+#define PHJ_GROW_BUCKETS_ALLOCATING 1
+#define PHJ_GROW_BUCKETS_REINSERTING 2
+#define PHJ_GROW_BUCKETS_PHASE(n) ((n) % 3) /* circular phases */
+
+typedef struct HashJoinTableData
+{
+ int nbuckets; /* # buckets in the in-memory hash table */
+ int log2_nbuckets; /* its log2 (nbuckets must be a power of 2) */
+
+ int nbuckets_original; /* # buckets when starting the first hash */
+ int nbuckets_optimal; /* optimal # buckets (per batch) */
+ int log2_nbuckets_optimal; /* log2(nbuckets_optimal) */
+
+ /* buckets[i] is head of list of tuples in i'th in-memory bucket */
+ union
+ {
+ /* unshared array is per-batch storage, as are all the tuples */
+ struct HashJoinTupleData **unshared;
+ /* shared array is per-query DSA area, as are all the tuples */
+ dsa_pointer_atomic *shared;
+ } buckets;
+
+ bool keepNulls; /* true to store unmatchable NULL tuples */
+
+ bool skewEnabled; /* are we using skew optimization? */
+ HashSkewBucket **skewBucket; /* hashtable of skew buckets */
+ int skewBucketLen; /* size of skewBucket array (a power of 2!) */
+ int nSkewBuckets; /* number of active skew buckets */
+ int *skewBucketNums; /* array indexes of active skew buckets */
+
+ int nbatch; /* number of batches */
+ int curbatch; /* current batch #; 0 during 1st pass */
+
+ int nbatch_original; /* nbatch when we started inner scan */
+ int nbatch_outstart; /* nbatch when we started outer scan */
+
+ bool growEnabled; /* flag to shut off nbatch increases */
+
+ double totalTuples; /* # tuples obtained from inner plan */
+ double partialTuples; /* # tuples obtained from inner plan by me */
+ double skewTuples; /* # tuples inserted into skew tuples */
+
+ /*
+ * These arrays are allocated for the life of the hash join, but only if
+ * nbatch > 1. A file is opened only when we first write a tuple into it
+ * (otherwise its pointer remains NULL). Note that the zero'th array
+ * elements never get used, since we will process rather than dump out any
+ * tuples of batch zero.
+ */
+ BufFile **innerBatchFile; /* buffered virtual temp file per batch */
+ BufFile **outerBatchFile; /* buffered virtual temp file per batch */
+
+ /*
+ * Info about the datatype-specific hash functions for the datatypes being
+ * hashed. These are arrays of the same length as the number of hash join
+ * clauses (hash keys).
+ */
+ FmgrInfo *outer_hashfunctions; /* lookup data for hash functions */
+ FmgrInfo *inner_hashfunctions; /* lookup data for hash functions */
+ bool *hashStrict; /* is each hash join operator strict? */
+ Oid *collations;
+
+ Size spaceUsed; /* memory space currently used by tuples */
+ Size spaceAllowed; /* upper limit for space used */
+ Size spacePeak; /* peak space used */
+ Size spaceUsedSkew; /* skew hash table's current space usage */
+ Size spaceAllowedSkew; /* upper limit for skew hashtable */
+
+ MemoryContext hashCxt; /* context for whole-hash-join storage */
+ MemoryContext batchCxt; /* context for this-batch-only storage */
+
+ /* used for dense allocation of tuples (into linked chunks) */
+ HashMemoryChunk chunks; /* one list for the whole batch */
+
+ /* Shared and private state for Parallel Hash. */
+ HashMemoryChunk current_chunk; /* this backend's current chunk */
+ dsa_area *area; /* DSA area to allocate memory from */
+ ParallelHashJoinState *parallel_state;
+ ParallelHashJoinBatchAccessor *batches;
+ dsa_pointer current_chunk_shared;
+} HashJoinTableData;
+
+#endif /* HASHJOIN_H */
diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h
new file mode 100644
index 0000000..2f9905b
--- /dev/null
+++ b/src/include/executor/instrument.h
@@ -0,0 +1,116 @@
+/*-------------------------------------------------------------------------
+ *
+ * instrument.h
+ * definitions for run-time statistics collection
+ *
+ *
+ * Copyright (c) 2001-2021, PostgreSQL Global Development Group
+ *
+ * src/include/executor/instrument.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INSTRUMENT_H
+#define INSTRUMENT_H
+
+#include "portability/instr_time.h"
+
+
+/*
+ * BufferUsage and WalUsage counters keep being incremented infinitely,
+ * i.e., must never be reset to zero, so that we can calculate how much
+ * the counters are incremented in an arbitrary period.
+ */
+typedef struct BufferUsage
+{
+ int64 shared_blks_hit; /* # of shared buffer hits */
+ int64 shared_blks_read; /* # of shared disk blocks read */
+ int64 shared_blks_dirtied; /* # of shared blocks dirtied */
+ int64 shared_blks_written; /* # of shared disk blocks written */
+ int64 local_blks_hit; /* # of local buffer hits */
+ int64 local_blks_read; /* # of local disk blocks read */
+ int64 local_blks_dirtied; /* # of local blocks dirtied */
+ int64 local_blks_written; /* # of local disk blocks written */
+ int64 temp_blks_read; /* # of temp blocks read */
+ int64 temp_blks_written; /* # of temp blocks written */
+ instr_time blk_read_time; /* time spent reading */
+ instr_time blk_write_time; /* time spent writing */
+} BufferUsage;
+
+/*
+ * WalUsage tracks only WAL activity like WAL records generation that
+ * can be measured per query and is displayed by EXPLAIN command,
+ * pg_stat_statements extension, etc. It does not track other WAL activity
+ * like WAL writes that it's not worth measuring per query. That's tracked
+ * by WAL global statistics counters in WalStats, instead.
+ */
+typedef struct WalUsage
+{
+ int64 wal_records; /* # of WAL records produced */
+ int64 wal_fpi; /* # of WAL full page images produced */
+ uint64 wal_bytes; /* size of WAL records produced */
+} WalUsage;
+
+/* Flag bits included in InstrAlloc's instrument_options bitmask */
+typedef enum InstrumentOption
+{
+ INSTRUMENT_TIMER = 1 << 0, /* needs timer (and row counts) */
+ INSTRUMENT_BUFFERS = 1 << 1, /* needs buffer usage */
+ INSTRUMENT_ROWS = 1 << 2, /* needs row count */
+ INSTRUMENT_WAL = 1 << 3, /* needs WAL usage */
+ INSTRUMENT_ALL = PG_INT32_MAX
+} InstrumentOption;
+
+typedef struct Instrumentation
+{
+ /* Parameters set at node creation: */
+ bool need_timer; /* true if we need timer data */
+ bool need_bufusage; /* true if we need buffer usage data */
+ bool need_walusage; /* true if we need WAL usage data */
+ bool async_mode; /* true if node is in async mode */
+ /* Info about current plan cycle: */
+ bool running; /* true if we've completed first tuple */
+ instr_time starttime; /* start time of current iteration of node */
+ instr_time counter; /* accumulated runtime for this node */
+ double firsttuple; /* time for first tuple of this cycle */
+ double tuplecount; /* # of tuples emitted so far this cycle */
+ BufferUsage bufusage_start; /* buffer usage at start */
+ WalUsage walusage_start; /* WAL usage at start */
+ /* Accumulated statistics across all completed cycles: */
+ double startup; /* total startup time (in seconds) */
+ double total; /* total time (in seconds) */
+ double ntuples; /* total tuples produced */
+ double ntuples2; /* secondary node-specific tuple counter */
+ double nloops; /* # of run cycles for this node */
+ double nfiltered1; /* # of tuples removed by scanqual or joinqual */
+ double nfiltered2; /* # of tuples removed by "other" quals */
+ BufferUsage bufusage; /* total buffer usage */
+ WalUsage walusage; /* total WAL usage */
+} Instrumentation;
+
+typedef struct WorkerInstrumentation
+{
+ int num_workers; /* # of structures that follow */
+ Instrumentation instrument[FLEXIBLE_ARRAY_MEMBER];
+} WorkerInstrumentation;
+
+extern PGDLLIMPORT BufferUsage pgBufferUsage;
+extern PGDLLIMPORT WalUsage pgWalUsage;
+
+extern Instrumentation *InstrAlloc(int n, int instrument_options,
+ bool async_mode);
+extern void InstrInit(Instrumentation *instr, int instrument_options);
+extern void InstrStartNode(Instrumentation *instr);
+extern void InstrStopNode(Instrumentation *instr, double nTuples);
+extern void InstrUpdateTupleCount(Instrumentation *instr, double nTuples);
+extern void InstrEndLoop(Instrumentation *instr);
+extern void InstrAggNode(Instrumentation *dst, Instrumentation *add);
+extern void InstrStartParallelQuery(void);
+extern void InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage);
+extern void InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage);
+extern void BufferUsageAccumDiff(BufferUsage *dst,
+ const BufferUsage *add, const BufferUsage *sub);
+extern void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add,
+ const WalUsage *sub);
+
+#endif /* INSTRUMENT_H */
diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h
new file mode 100644
index 0000000..398446d
--- /dev/null
+++ b/src/include/executor/nodeAgg.h
@@ -0,0 +1,333 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeAgg.h
+ * prototypes for nodeAgg.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeAgg.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEAGG_H
+#define NODEAGG_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+
+/*
+ * AggStatePerTransData - per aggregate state value information
+ *
+ * Working state for updating the aggregate's state value, by calling the
+ * transition function with an input row. This struct does not store the
+ * information needed to produce the final aggregate result from the transition
+ * state, that's stored in AggStatePerAggData instead. This separation allows
+ * multiple aggregate results to be produced from a single state value.
+ */
+typedef struct AggStatePerTransData
+{
+ /*
+ * These values are set up during ExecInitAgg() and do not change
+ * thereafter:
+ */
+
+ /*
+ * Link to an Aggref expr this state value is for.
+ *
+ * There can be multiple Aggref's sharing the same state value, so long as
+ * the inputs and transition functions are identical and the final
+ * functions are not read-write. This points to the first one of them.
+ */
+ Aggref *aggref;
+
+ /*
+ * Is this state value actually being shared by more than one Aggref?
+ */
+ bool aggshared;
+
+ /*
+ * Number of aggregated input columns. This includes ORDER BY expressions
+ * in both the plain-agg and ordered-set cases. Ordered-set direct args
+ * are not counted, though.
+ */
+ int numInputs;
+
+ /*
+ * Number of aggregated input columns to pass to the transfn. This
+ * includes the ORDER BY columns for ordered-set aggs, but not for plain
+ * aggs. (This doesn't count the transition state value!)
+ */
+ int numTransInputs;
+
+ /* Oid of the state transition or combine function */
+ Oid transfn_oid;
+
+ /* Oid of the serialization function or InvalidOid */
+ Oid serialfn_oid;
+
+ /* Oid of the deserialization function or InvalidOid */
+ Oid deserialfn_oid;
+
+ /* Oid of state value's datatype */
+ Oid aggtranstype;
+
+ /*
+ * fmgr lookup data for transition function or combine function. Note in
+ * particular that the fn_strict flag is kept here.
+ */
+ FmgrInfo transfn;
+
+ /* fmgr lookup data for serialization function */
+ FmgrInfo serialfn;
+
+ /* fmgr lookup data for deserialization function */
+ FmgrInfo deserialfn;
+
+ /* Input collation derived for aggregate */
+ Oid aggCollation;
+
+ /* number of sorting columns */
+ int numSortCols;
+
+ /* number of sorting columns to consider in DISTINCT comparisons */
+ /* (this is either zero or the same as numSortCols) */
+ int numDistinctCols;
+
+ /* deconstructed sorting information (arrays of length numSortCols) */
+ AttrNumber *sortColIdx;
+ Oid *sortOperators;
+ Oid *sortCollations;
+ bool *sortNullsFirst;
+
+ /*
+ * Comparators for input columns --- only set/used when aggregate has
+ * DISTINCT flag. equalfnOne version is used for single-column
+ * comparisons, equalfnMulti for the case of multiple columns.
+ */
+ FmgrInfo equalfnOne;
+ ExprState *equalfnMulti;
+
+ /*
+ * initial value from pg_aggregate entry
+ */
+ Datum initValue;
+ bool initValueIsNull;
+
+ /*
+ * We need the len and byval info for the agg's input and transition data
+ * types in order to know how to copy/delete values.
+ *
+ * Note that the info for the input type is used only when handling
+ * DISTINCT aggs with just one argument, so there is only one input type.
+ */
+ int16 inputtypeLen,
+ transtypeLen;
+ bool inputtypeByVal,
+ transtypeByVal;
+
+ /*
+ * Slots for holding the evaluated input arguments. These are set up
+ * during ExecInitAgg() and then used for each input row requiring either
+ * FILTER or ORDER BY/DISTINCT processing.
+ */
+ TupleTableSlot *sortslot; /* current input tuple */
+ TupleTableSlot *uniqslot; /* used for multi-column DISTINCT */
+ TupleDesc sortdesc; /* descriptor of input tuples */
+
+ /*
+ * These values are working state that is initialized at the start of an
+ * input tuple group and updated for each input tuple.
+ *
+ * For a simple (non DISTINCT/ORDER BY) aggregate, we just feed the input
+ * values straight to the transition function. If it's DISTINCT or
+ * requires ORDER BY, we pass the input values into a Tuplesort object;
+ * then at completion of the input tuple group, we scan the sorted values,
+ * eliminate duplicates if needed, and run the transition function on the
+ * rest.
+ *
+ * We need a separate tuplesort for each grouping set.
+ */
+
+ Tuplesortstate **sortstates; /* sort objects, if DISTINCT or ORDER BY */
+
+ /*
+ * This field is a pre-initialized FunctionCallInfo struct used for
+ * calling this aggregate's transfn. We save a few cycles per row by not
+ * re-initializing the unchanging fields; which isn't much, but it seems
+ * worth the extra space consumption.
+ */
+ FunctionCallInfo transfn_fcinfo;
+
+ /* Likewise for serialization and deserialization functions */
+ FunctionCallInfo serialfn_fcinfo;
+
+ FunctionCallInfo deserialfn_fcinfo;
+} AggStatePerTransData;
+
+/*
+ * AggStatePerAggData - per-aggregate information
+ *
+ * This contains the information needed to call the final function, to produce
+ * a final aggregate result from the state value. If there are multiple
+ * identical Aggrefs in the query, they can all share the same per-agg data.
+ *
+ * These values are set up during ExecInitAgg() and do not change thereafter.
+ */
+typedef struct AggStatePerAggData
+{
+ /*
+ * Link to an Aggref expr this state value is for.
+ *
+ * There can be multiple identical Aggref's sharing the same per-agg. This
+ * points to the first one of them.
+ */
+ Aggref *aggref;
+
+ /* index to the state value which this agg should use */
+ int transno;
+
+ /* Optional Oid of final function (may be InvalidOid) */
+ Oid finalfn_oid;
+
+ /*
+ * fmgr lookup data for final function --- only valid when finalfn_oid is
+ * not InvalidOid.
+ */
+ FmgrInfo finalfn;
+
+ /*
+ * Number of arguments to pass to the finalfn. This is always at least 1
+ * (the transition state value) plus any ordered-set direct args. If the
+ * finalfn wants extra args then we pass nulls corresponding to the
+ * aggregated input columns.
+ */
+ int numFinalArgs;
+
+ /* ExprStates for any direct-argument expressions */
+ List *aggdirectargs;
+
+ /*
+ * We need the len and byval info for the agg's result data type in order
+ * to know how to copy/delete values.
+ */
+ int16 resulttypeLen;
+ bool resulttypeByVal;
+
+ /*
+ * "shareable" is false if this agg cannot share state values with other
+ * aggregates because the final function is read-write.
+ */
+ bool shareable;
+} AggStatePerAggData;
+
+/*
+ * AggStatePerGroupData - per-aggregate-per-group working state
+ *
+ * These values are working state that is initialized at the start of
+ * an input tuple group and updated for each input tuple.
+ *
+ * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
+ * structs (pointed to by aggstate->pergroup); we re-use the array for
+ * each input group, if it's AGG_SORTED mode. In AGG_HASHED mode, the
+ * hash table contains an array of these structs for each tuple group.
+ *
+ * Logically, the sortstate field belongs in this struct, but we do not
+ * keep it here for space reasons: we don't support DISTINCT aggregates
+ * in AGG_HASHED mode, so there's no reason to use up a pointer field
+ * in every entry of the hashtable.
+ */
+typedef struct AggStatePerGroupData
+{
+#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE 0
+ Datum transValue; /* current transition value */
+#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL 1
+ bool transValueIsNull;
+
+#define FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE 2
+ bool noTransValue; /* true if transValue not set yet */
+
+ /*
+ * Note: noTransValue initially has the same value as transValueIsNull,
+ * and if true both are cleared to false at the same time. They are not
+ * the same though: if transfn later returns a NULL, we want to keep that
+ * NULL and not auto-replace it with a later input value. Only the first
+ * non-NULL input will be auto-substituted.
+ */
+} AggStatePerGroupData;
+
+/*
+ * AggStatePerPhaseData - per-grouping-set-phase state
+ *
+ * Grouping sets are divided into "phases", where a single phase can be
+ * processed in one pass over the input. If there is more than one phase, then
+ * at the end of input from the current phase, state is reset and another pass
+ * taken over the data which has been re-sorted in the mean time.
+ *
+ * Accordingly, each phase specifies a list of grouping sets and group clause
+ * information, plus each phase after the first also has a sort order.
+ */
+typedef struct AggStatePerPhaseData
+{
+ AggStrategy aggstrategy; /* strategy for this phase */
+ int numsets; /* number of grouping sets (or 0) */
+ int *gset_lengths; /* lengths of grouping sets */
+ Bitmapset **grouped_cols; /* column groupings for rollup */
+ ExprState **eqfunctions; /* expression returning equality, indexed by
+ * nr of cols to compare */
+ Agg *aggnode; /* Agg node for phase data */
+ Sort *sortnode; /* Sort node for input ordering for phase */
+
+ ExprState *evaltrans; /* evaluation of transition functions */
+
+ /*----------
+ * Cached variants of the compiled expression.
+ * first subscript: 0: outerops; 1: TTSOpsMinimalTuple
+ * second subscript: 0: no NULL check; 1: with NULL check
+ *----------
+ */
+ ExprState *evaltrans_cache[2][2];
+} AggStatePerPhaseData;
+
+/*
+ * AggStatePerHashData - per-hashtable state
+ *
+ * When doing grouping sets with hashing, we have one of these for each
+ * grouping set. (When doing hashing without grouping sets, we have just one of
+ * them.)
+ */
+typedef struct AggStatePerHashData
+{
+ TupleHashTable hashtable; /* hash table with one entry per group */
+ TupleHashIterator hashiter; /* for iterating through hash table */
+ TupleTableSlot *hashslot; /* slot for loading hash table */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ Oid *eqfuncoids; /* per-grouping-field equality fns */
+ int numCols; /* number of hash key columns */
+ int numhashGrpCols; /* number of columns in hash table */
+ int largestGrpColIdx; /* largest col required for hashing */
+ AttrNumber *hashGrpColIdxInput; /* hash col indices in input slot */
+ AttrNumber *hashGrpColIdxHash; /* indices in hash table tuples */
+ Agg *aggnode; /* original Agg node, for numGroups etc. */
+} AggStatePerHashData;
+
+
+extern AggState *ExecInitAgg(Agg *node, EState *estate, int eflags);
+extern void ExecEndAgg(AggState *node);
+extern void ExecReScanAgg(AggState *node);
+
+extern Size hash_agg_entry_size(int numTrans, Size tupleWidth,
+ Size transitionSpace);
+extern void hash_agg_set_limits(double hashentrysize, double input_groups,
+ int used_bits, Size *mem_limit,
+ uint64 *ngroups_limit, int *num_partitions);
+
+/* parallel instrumentation support */
+extern void ExecAggEstimate(AggState *node, ParallelContext *pcxt);
+extern void ExecAggInitializeDSM(AggState *node, ParallelContext *pcxt);
+extern void ExecAggInitializeWorker(AggState *node, ParallelWorkerContext *pwcxt);
+extern void ExecAggRetrieveInstrumentation(AggState *node);
+
+#endif /* NODEAGG_H */
diff --git a/src/include/executor/nodeAppend.h b/src/include/executor/nodeAppend.h
new file mode 100644
index 0000000..fa54ac6
--- /dev/null
+++ b/src/include/executor/nodeAppend.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeAppend.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeAppend.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEAPPEND_H
+#define NODEAPPEND_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern AppendState *ExecInitAppend(Append *node, EState *estate, int eflags);
+extern void ExecEndAppend(AppendState *node);
+extern void ExecReScanAppend(AppendState *node);
+extern void ExecAppendEstimate(AppendState *node, ParallelContext *pcxt);
+extern void ExecAppendInitializeDSM(AppendState *node, ParallelContext *pcxt);
+extern void ExecAppendReInitializeDSM(AppendState *node, ParallelContext *pcxt);
+extern void ExecAppendInitializeWorker(AppendState *node, ParallelWorkerContext *pwcxt);
+
+extern void ExecAsyncAppendResponse(AsyncRequest *areq);
+
+#endif /* NODEAPPEND_H */
diff --git a/src/include/executor/nodeBitmapAnd.h b/src/include/executor/nodeBitmapAnd.h
new file mode 100644
index 0000000..ac5d4ae
--- /dev/null
+++ b/src/include/executor/nodeBitmapAnd.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapAnd.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapAnd.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPAND_H
+#define NODEBITMAPAND_H
+
+#include "nodes/execnodes.h"
+
+extern BitmapAndState *ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags);
+extern Node *MultiExecBitmapAnd(BitmapAndState *node);
+extern void ExecEndBitmapAnd(BitmapAndState *node);
+extern void ExecReScanBitmapAnd(BitmapAndState *node);
+
+#endif /* NODEBITMAPAND_H */
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
new file mode 100644
index 0000000..3b0bd5a
--- /dev/null
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapHeapscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapHeapscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPHEAPSCAN_H
+#define NODEBITMAPHEAPSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern BitmapHeapScanState *ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags);
+extern void ExecEndBitmapHeapScan(BitmapHeapScanState *node);
+extern void ExecReScanBitmapHeapScan(BitmapHeapScanState *node);
+extern void ExecBitmapHeapEstimate(BitmapHeapScanState *node,
+ ParallelContext *pcxt);
+extern void ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
+ ParallelContext *pcxt);
+extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
+ ParallelContext *pcxt);
+extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+#endif /* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/executor/nodeBitmapIndexscan.h b/src/include/executor/nodeBitmapIndexscan.h
new file mode 100644
index 0000000..95bf228
--- /dev/null
+++ b/src/include/executor/nodeBitmapIndexscan.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapIndexscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapIndexscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPINDEXSCAN_H
+#define NODEBITMAPINDEXSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern BitmapIndexScanState *ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags);
+extern Node *MultiExecBitmapIndexScan(BitmapIndexScanState *node);
+extern void ExecEndBitmapIndexScan(BitmapIndexScanState *node);
+extern void ExecReScanBitmapIndexScan(BitmapIndexScanState *node);
+
+#endif /* NODEBITMAPINDEXSCAN_H */
diff --git a/src/include/executor/nodeBitmapOr.h b/src/include/executor/nodeBitmapOr.h
new file mode 100644
index 0000000..1c1da2f
--- /dev/null
+++ b/src/include/executor/nodeBitmapOr.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapOr.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapOr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPOR_H
+#define NODEBITMAPOR_H
+
+#include "nodes/execnodes.h"
+
+extern BitmapOrState *ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags);
+extern Node *MultiExecBitmapOr(BitmapOrState *node);
+extern void ExecEndBitmapOr(BitmapOrState *node);
+extern void ExecReScanBitmapOr(BitmapOrState *node);
+
+#endif /* NODEBITMAPOR_H */
diff --git a/src/include/executor/nodeCtescan.h b/src/include/executor/nodeCtescan.h
new file mode 100644
index 0000000..2c33442
--- /dev/null
+++ b/src/include/executor/nodeCtescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeCtescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeCtescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODECTESCAN_H
+#define NODECTESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern CteScanState *ExecInitCteScan(CteScan *node, EState *estate, int eflags);
+extern void ExecEndCteScan(CteScanState *node);
+extern void ExecReScanCteScan(CteScanState *node);
+
+#endif /* NODECTESCAN_H */
diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h
new file mode 100644
index 0000000..0be69a5
--- /dev/null
+++ b/src/include/executor/nodeCustom.h
@@ -0,0 +1,42 @@
+/* ------------------------------------------------------------------------
+ *
+ * nodeCustom.h
+ *
+ * prototypes for CustomScan nodes
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * ------------------------------------------------------------------------
+ */
+#ifndef NODECUSTOM_H
+#define NODECUSTOM_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+/*
+ * General executor code
+ */
+extern CustomScanState *ExecInitCustomScan(CustomScan *cscan,
+ EState *estate, int eflags);
+extern void ExecEndCustomScan(CustomScanState *node);
+
+extern void ExecReScanCustomScan(CustomScanState *node);
+extern void ExecCustomMarkPos(CustomScanState *node);
+extern void ExecCustomRestrPos(CustomScanState *node);
+
+/*
+ * Parallel execution support
+ */
+extern void ExecCustomScanEstimate(CustomScanState *node,
+ ParallelContext *pcxt);
+extern void ExecCustomScanInitializeDSM(CustomScanState *node,
+ ParallelContext *pcxt);
+extern void ExecCustomScanReInitializeDSM(CustomScanState *node,
+ ParallelContext *pcxt);
+extern void ExecCustomScanInitializeWorker(CustomScanState *node,
+ ParallelWorkerContext *pwcxt);
+extern void ExecShutdownCustomScan(CustomScanState *node);
+
+#endif /* NODECUSTOM_H */
diff --git a/src/include/executor/nodeForeignscan.h b/src/include/executor/nodeForeignscan.h
new file mode 100644
index 0000000..8ffc0ca
--- /dev/null
+++ b/src/include/executor/nodeForeignscan.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeForeignscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeForeignscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEFOREIGNSCAN_H
+#define NODEFOREIGNSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern ForeignScanState *ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags);
+extern void ExecEndForeignScan(ForeignScanState *node);
+extern void ExecReScanForeignScan(ForeignScanState *node);
+
+extern void ExecForeignScanEstimate(ForeignScanState *node,
+ ParallelContext *pcxt);
+extern void ExecForeignScanInitializeDSM(ForeignScanState *node,
+ ParallelContext *pcxt);
+extern void ExecForeignScanReInitializeDSM(ForeignScanState *node,
+ ParallelContext *pcxt);
+extern void ExecForeignScanInitializeWorker(ForeignScanState *node,
+ ParallelWorkerContext *pwcxt);
+extern void ExecShutdownForeignScan(ForeignScanState *node);
+
+extern void ExecAsyncForeignScanRequest(AsyncRequest *areq);
+extern void ExecAsyncForeignScanConfigureWait(AsyncRequest *areq);
+extern void ExecAsyncForeignScanNotify(AsyncRequest *areq);
+
+#endif /* NODEFOREIGNSCAN_H */
diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h
new file mode 100644
index 0000000..8f210a7
--- /dev/null
+++ b/src/include/executor/nodeFunctionscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeFunctionscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeFunctionscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEFUNCTIONSCAN_H
+#define NODEFUNCTIONSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags);
+extern void ExecEndFunctionScan(FunctionScanState *node);
+extern void ExecReScanFunctionScan(FunctionScanState *node);
+
+#endif /* NODEFUNCTIONSCAN_H */
diff --git a/src/include/executor/nodeGather.h b/src/include/executor/nodeGather.h
new file mode 100644
index 0000000..e7c92b8
--- /dev/null
+++ b/src/include/executor/nodeGather.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeGather.h
+ * prototypes for nodeGather.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeGather.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEGATHER_H
+#define NODEGATHER_H
+
+#include "nodes/execnodes.h"
+
+extern GatherState *ExecInitGather(Gather *node, EState *estate, int eflags);
+extern void ExecEndGather(GatherState *node);
+extern void ExecShutdownGather(GatherState *node);
+extern void ExecReScanGather(GatherState *node);
+
+#endif /* NODEGATHER_H */
diff --git a/src/include/executor/nodeGatherMerge.h b/src/include/executor/nodeGatherMerge.h
new file mode 100644
index 0000000..65e7245
--- /dev/null
+++ b/src/include/executor/nodeGatherMerge.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeGatherMerge.h
+ * prototypes for nodeGatherMerge.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeGatherMerge.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEGATHERMERGE_H
+#define NODEGATHERMERGE_H
+
+#include "nodes/execnodes.h"
+
+extern GatherMergeState *ExecInitGatherMerge(GatherMerge *node,
+ EState *estate,
+ int eflags);
+extern void ExecEndGatherMerge(GatherMergeState *node);
+extern void ExecReScanGatherMerge(GatherMergeState *node);
+extern void ExecShutdownGatherMerge(GatherMergeState *node);
+
+#endif /* NODEGATHERMERGE_H */
diff --git a/src/include/executor/nodeGroup.h b/src/include/executor/nodeGroup.h
new file mode 100644
index 0000000..8cb2e09
--- /dev/null
+++ b/src/include/executor/nodeGroup.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeGroup.h
+ * prototypes for nodeGroup.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeGroup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEGROUP_H
+#define NODEGROUP_H
+
+#include "nodes/execnodes.h"
+
+extern GroupState *ExecInitGroup(Group *node, EState *estate, int eflags);
+extern void ExecEndGroup(GroupState *node);
+extern void ExecReScanGroup(GroupState *node);
+
+#endif /* NODEGROUP_H */
diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h
new file mode 100644
index 0000000..3fbe02e
--- /dev/null
+++ b/src/include/executor/nodeHash.h
@@ -0,0 +1,79 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeHash.h
+ * prototypes for nodeHash.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeHash.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEHASH_H
+#define NODEHASH_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+struct SharedHashJoinBatch;
+
+extern HashState *ExecInitHash(Hash *node, EState *estate, int eflags);
+extern Node *MultiExecHash(HashState *node);
+extern void ExecEndHash(HashState *node);
+extern void ExecReScanHash(HashState *node);
+
+extern HashJoinTable ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations,
+ bool keepNulls);
+extern void ExecParallelHashTableAlloc(HashJoinTable hashtable,
+ int batchno);
+extern void ExecHashTableDestroy(HashJoinTable hashtable);
+extern void ExecHashTableDetach(HashJoinTable hashtable);
+extern void ExecHashTableDetachBatch(HashJoinTable hashtable);
+extern void ExecParallelHashTableSetCurrentBatch(HashJoinTable hashtable,
+ int batchno);
+
+extern void ExecHashTableInsert(HashJoinTable hashtable,
+ TupleTableSlot *slot,
+ uint32 hashvalue);
+extern void ExecParallelHashTableInsert(HashJoinTable hashtable,
+ TupleTableSlot *slot,
+ uint32 hashvalue);
+extern void ExecParallelHashTableInsertCurrentBatch(HashJoinTable hashtable,
+ TupleTableSlot *slot,
+ uint32 hashvalue);
+extern bool ExecHashGetHashValue(HashJoinTable hashtable,
+ ExprContext *econtext,
+ List *hashkeys,
+ bool outer_tuple,
+ bool keep_nulls,
+ uint32 *hashvalue);
+extern void ExecHashGetBucketAndBatch(HashJoinTable hashtable,
+ uint32 hashvalue,
+ int *bucketno,
+ int *batchno);
+extern bool ExecScanHashBucket(HashJoinState *hjstate, ExprContext *econtext);
+extern bool ExecParallelScanHashBucket(HashJoinState *hjstate, ExprContext *econtext);
+extern void ExecPrepHashTableForUnmatched(HashJoinState *hjstate);
+extern bool ExecScanHashTableForUnmatched(HashJoinState *hjstate,
+ ExprContext *econtext);
+extern void ExecHashTableReset(HashJoinTable hashtable);
+extern void ExecHashTableResetMatchFlags(HashJoinTable hashtable);
+extern void ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
+ bool try_combined_hash_mem,
+ int parallel_workers,
+ size_t *space_allowed,
+ int *numbuckets,
+ int *numbatches,
+ int *num_skew_mcvs);
+extern int ExecHashGetSkewBucket(HashJoinTable hashtable, uint32 hashvalue);
+extern void ExecHashEstimate(HashState *node, ParallelContext *pcxt);
+extern void ExecHashInitializeDSM(HashState *node, ParallelContext *pcxt);
+extern void ExecHashInitializeWorker(HashState *node, ParallelWorkerContext *pwcxt);
+extern void ExecHashRetrieveInstrumentation(HashState *node);
+extern void ExecShutdownHash(HashState *node);
+extern void ExecHashAccumInstrumentation(HashInstrumentation *instrument,
+ HashJoinTable hashtable);
+
+#endif /* NODEHASH_H */
diff --git a/src/include/executor/nodeHashjoin.h b/src/include/executor/nodeHashjoin.h
new file mode 100644
index 0000000..7d6541a
--- /dev/null
+++ b/src/include/executor/nodeHashjoin.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeHashjoin.h
+ * prototypes for nodeHashjoin.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeHashjoin.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEHASHJOIN_H
+#define NODEHASHJOIN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+#include "storage/buffile.h"
+
+extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate, int eflags);
+extern void ExecEndHashJoin(HashJoinState *node);
+extern void ExecReScanHashJoin(HashJoinState *node);
+extern void ExecShutdownHashJoin(HashJoinState *node);
+extern void ExecHashJoinEstimate(HashJoinState *state, ParallelContext *pcxt);
+extern void ExecHashJoinInitializeDSM(HashJoinState *state, ParallelContext *pcxt);
+extern void ExecHashJoinReInitializeDSM(HashJoinState *state, ParallelContext *pcxt);
+extern void ExecHashJoinInitializeWorker(HashJoinState *state,
+ ParallelWorkerContext *pwcxt);
+
+extern void ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue,
+ BufFile **fileptr);
+
+#endif /* NODEHASHJOIN_H */
diff --git a/src/include/executor/nodeIncrementalSort.h b/src/include/executor/nodeIncrementalSort.h
new file mode 100644
index 0000000..0e14183
--- /dev/null
+++ b/src/include/executor/nodeIncrementalSort.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeIncrementalSort.h
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeIncrementalSort.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEINCREMENTALSORT_H
+#define NODEINCREMENTALSORT_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern IncrementalSortState *ExecInitIncrementalSort(IncrementalSort *node, EState *estate, int eflags);
+extern void ExecEndIncrementalSort(IncrementalSortState *node);
+extern void ExecReScanIncrementalSort(IncrementalSortState *node);
+
+/* parallel instrumentation support */
+extern void ExecIncrementalSortEstimate(IncrementalSortState *node, ParallelContext *pcxt);
+extern void ExecIncrementalSortInitializeDSM(IncrementalSortState *node, ParallelContext *pcxt);
+extern void ExecIncrementalSortInitializeWorker(IncrementalSortState *node, ParallelWorkerContext *pcxt);
+extern void ExecIncrementalSortRetrieveInstrumentation(IncrementalSortState *node);
+
+#endif /* NODEINCREMENTALSORT_H */
diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h
new file mode 100644
index 0000000..bcb266b
--- /dev/null
+++ b/src/include/executor/nodeIndexonlyscan.h
@@ -0,0 +1,36 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeIndexonlyscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeIndexonlyscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEINDEXONLYSCAN_H
+#define NODEINDEXONLYSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern IndexOnlyScanState *ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags);
+extern void ExecEndIndexOnlyScan(IndexOnlyScanState *node);
+extern void ExecIndexOnlyMarkPos(IndexOnlyScanState *node);
+extern void ExecIndexOnlyRestrPos(IndexOnlyScanState *node);
+extern void ExecReScanIndexOnlyScan(IndexOnlyScanState *node);
+
+/* Support functions for parallel index-only scans */
+extern void ExecIndexOnlyScanEstimate(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanReInitializeDSM(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+#endif /* NODEINDEXONLYSCAN_H */
diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h
new file mode 100644
index 0000000..70a2cff
--- /dev/null
+++ b/src/include/executor/nodeIndexscan.h
@@ -0,0 +1,47 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeIndexscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeIndexscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEINDEXSCAN_H
+#define NODEINDEXSCAN_H
+
+#include "access/genam.h"
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern IndexScanState *ExecInitIndexScan(IndexScan *node, EState *estate, int eflags);
+extern void ExecEndIndexScan(IndexScanState *node);
+extern void ExecIndexMarkPos(IndexScanState *node);
+extern void ExecIndexRestrPos(IndexScanState *node);
+extern void ExecReScanIndexScan(IndexScanState *node);
+extern void ExecIndexScanEstimate(IndexScanState *node, ParallelContext *pcxt);
+extern void ExecIndexScanInitializeDSM(IndexScanState *node, ParallelContext *pcxt);
+extern void ExecIndexScanReInitializeDSM(IndexScanState *node, ParallelContext *pcxt);
+extern void ExecIndexScanInitializeWorker(IndexScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+/*
+ * These routines are exported to share code with nodeIndexonlyscan.c and
+ * nodeBitmapIndexscan.c
+ */
+extern void ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
+ List *quals, bool isorderby,
+ ScanKey *scanKeys, int *numScanKeys,
+ IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys,
+ IndexArrayKeyInfo **arrayKeys, int *numArrayKeys);
+extern void ExecIndexEvalRuntimeKeys(ExprContext *econtext,
+ IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys);
+extern bool ExecIndexEvalArrayKeys(ExprContext *econtext,
+ IndexArrayKeyInfo *arrayKeys, int numArrayKeys);
+extern bool ExecIndexAdvanceArrayKeys(IndexArrayKeyInfo *arrayKeys, int numArrayKeys);
+
+#endif /* NODEINDEXSCAN_H */
diff --git a/src/include/executor/nodeLimit.h b/src/include/executor/nodeLimit.h
new file mode 100644
index 0000000..789871f
--- /dev/null
+++ b/src/include/executor/nodeLimit.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeLimit.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeLimit.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODELIMIT_H
+#define NODELIMIT_H
+
+#include "nodes/execnodes.h"
+
+extern LimitState *ExecInitLimit(Limit *node, EState *estate, int eflags);
+extern void ExecEndLimit(LimitState *node);
+extern void ExecReScanLimit(LimitState *node);
+
+#endif /* NODELIMIT_H */
diff --git a/src/include/executor/nodeLockRows.h b/src/include/executor/nodeLockRows.h
new file mode 100644
index 0000000..ca4b72a
--- /dev/null
+++ b/src/include/executor/nodeLockRows.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeLockRows.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeLockRows.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODELOCKROWS_H
+#define NODELOCKROWS_H
+
+#include "nodes/execnodes.h"
+
+extern LockRowsState *ExecInitLockRows(LockRows *node, EState *estate, int eflags);
+extern void ExecEndLockRows(LockRowsState *node);
+extern void ExecReScanLockRows(LockRowsState *node);
+
+#endif /* NODELOCKROWS_H */
diff --git a/src/include/executor/nodeMaterial.h b/src/include/executor/nodeMaterial.h
new file mode 100644
index 0000000..3acfc88
--- /dev/null
+++ b/src/include/executor/nodeMaterial.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeMaterial.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeMaterial.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMATERIAL_H
+#define NODEMATERIAL_H
+
+#include "nodes/execnodes.h"
+
+extern MaterialState *ExecInitMaterial(Material *node, EState *estate, int eflags);
+extern void ExecEndMaterial(MaterialState *node);
+extern void ExecMaterialMarkPos(MaterialState *node);
+extern void ExecMaterialRestrPos(MaterialState *node);
+extern void ExecReScanMaterial(MaterialState *node);
+
+#endif /* NODEMATERIAL_H */
diff --git a/src/include/executor/nodeMemoize.h b/src/include/executor/nodeMemoize.h
new file mode 100644
index 0000000..898fa43
--- /dev/null
+++ b/src/include/executor/nodeMemoize.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeMemoize.h
+ *
+ *
+ *
+ * Portions Copyright (c) 2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeMemoize.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMEMOIZE_H
+#define NODEMEMOIZE_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern MemoizeState *ExecInitMemoize(Memoize *node, EState *estate, int eflags);
+extern void ExecEndMemoize(MemoizeState *node);
+extern void ExecReScanMemoize(MemoizeState *node);
+extern double ExecEstimateCacheEntryOverheadBytes(double ntuples);
+extern void ExecMemoizeEstimate(MemoizeState *node,
+ ParallelContext *pcxt);
+extern void ExecMemoizeInitializeDSM(MemoizeState *node,
+ ParallelContext *pcxt);
+extern void ExecMemoizeInitializeWorker(MemoizeState *node,
+ ParallelWorkerContext *pwcxt);
+extern void ExecMemoizeRetrieveInstrumentation(MemoizeState *node);
+
+#endif /* NODEMEMOIZE_H */
diff --git a/src/include/executor/nodeMergeAppend.h b/src/include/executor/nodeMergeAppend.h
new file mode 100644
index 0000000..eb54c2f
--- /dev/null
+++ b/src/include/executor/nodeMergeAppend.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeMergeAppend.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeMergeAppend.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMERGEAPPEND_H
+#define NODEMERGEAPPEND_H
+
+#include "nodes/execnodes.h"
+
+extern MergeAppendState *ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags);
+extern void ExecEndMergeAppend(MergeAppendState *node);
+extern void ExecReScanMergeAppend(MergeAppendState *node);
+
+#endif /* NODEMERGEAPPEND_H */
diff --git a/src/include/executor/nodeMergejoin.h b/src/include/executor/nodeMergejoin.h
new file mode 100644
index 0000000..031d67d
--- /dev/null
+++ b/src/include/executor/nodeMergejoin.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeMergejoin.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeMergejoin.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMERGEJOIN_H
+#define NODEMERGEJOIN_H
+
+#include "nodes/execnodes.h"
+
+extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags);
+extern void ExecEndMergeJoin(MergeJoinState *node);
+extern void ExecReScanMergeJoin(MergeJoinState *node);
+
+#endif /* NODEMERGEJOIN_H */
diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h
new file mode 100644
index 0000000..83e2965
--- /dev/null
+++ b/src/include/executor/nodeModifyTable.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeModifyTable.h
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeModifyTable.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMODIFYTABLE_H
+#define NODEMODIFYTABLE_H
+
+#include "nodes/execnodes.h"
+
+extern void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo,
+ EState *estate, TupleTableSlot *slot,
+ CmdType cmdtype);
+
+extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags);
+extern void ExecEndModifyTable(ModifyTableState *node);
+extern void ExecReScanModifyTable(ModifyTableState *node);
+
+#endif /* NODEMODIFYTABLE_H */
diff --git a/src/include/executor/nodeNamedtuplestorescan.h b/src/include/executor/nodeNamedtuplestorescan.h
new file mode 100644
index 0000000..fd270a5
--- /dev/null
+++ b/src/include/executor/nodeNamedtuplestorescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeNamedtuplestorescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeNamedtuplestorescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODENAMEDTUPLESTORESCAN_H
+#define NODENAMEDTUPLESTORESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern NamedTuplestoreScanState *ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags);
+extern void ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node);
+extern void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node);
+
+#endif /* NODENAMEDTUPLESTORESCAN_H */
diff --git a/src/include/executor/nodeNestloop.h b/src/include/executor/nodeNestloop.h
new file mode 100644
index 0000000..9f32e92
--- /dev/null
+++ b/src/include/executor/nodeNestloop.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeNestloop.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeNestloop.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODENESTLOOP_H
+#define NODENESTLOOP_H
+
+#include "nodes/execnodes.h"
+
+extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate, int eflags);
+extern void ExecEndNestLoop(NestLoopState *node);
+extern void ExecReScanNestLoop(NestLoopState *node);
+
+#endif /* NODENESTLOOP_H */
diff --git a/src/include/executor/nodeProjectSet.h b/src/include/executor/nodeProjectSet.h
new file mode 100644
index 0000000..5852237
--- /dev/null
+++ b/src/include/executor/nodeProjectSet.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeProjectSet.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeProjectSet.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEPROJECTSET_H
+#define NODEPROJECTSET_H
+
+#include "nodes/execnodes.h"
+
+extern ProjectSetState *ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags);
+extern void ExecEndProjectSet(ProjectSetState *node);
+extern void ExecReScanProjectSet(ProjectSetState *node);
+
+#endif /* NODEPROJECTSET_H */
diff --git a/src/include/executor/nodeRecursiveunion.h b/src/include/executor/nodeRecursiveunion.h
new file mode 100644
index 0000000..b1f5f5d
--- /dev/null
+++ b/src/include/executor/nodeRecursiveunion.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeRecursiveunion.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeRecursiveunion.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODERECURSIVEUNION_H
+#define NODERECURSIVEUNION_H
+
+#include "nodes/execnodes.h"
+
+extern RecursiveUnionState *ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags);
+extern void ExecEndRecursiveUnion(RecursiveUnionState *node);
+extern void ExecReScanRecursiveUnion(RecursiveUnionState *node);
+
+#endif /* NODERECURSIVEUNION_H */
diff --git a/src/include/executor/nodeResult.h b/src/include/executor/nodeResult.h
new file mode 100644
index 0000000..197eaba
--- /dev/null
+++ b/src/include/executor/nodeResult.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeResult.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeResult.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODERESULT_H
+#define NODERESULT_H
+
+#include "nodes/execnodes.h"
+
+extern ResultState *ExecInitResult(Result *node, EState *estate, int eflags);
+extern void ExecEndResult(ResultState *node);
+extern void ExecResultMarkPos(ResultState *node);
+extern void ExecResultRestrPos(ResultState *node);
+extern void ExecReScanResult(ResultState *node);
+
+#endif /* NODERESULT_H */
diff --git a/src/include/executor/nodeSamplescan.h b/src/include/executor/nodeSamplescan.h
new file mode 100644
index 0000000..7142a8a
--- /dev/null
+++ b/src/include/executor/nodeSamplescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSamplescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSamplescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESAMPLESCAN_H
+#define NODESAMPLESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern SampleScanState *ExecInitSampleScan(SampleScan *node, EState *estate, int eflags);
+extern void ExecEndSampleScan(SampleScanState *node);
+extern void ExecReScanSampleScan(SampleScanState *node);
+
+#endif /* NODESAMPLESCAN_H */
diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h
new file mode 100644
index 0000000..ef1521c
--- /dev/null
+++ b/src/include/executor/nodeSeqscan.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSeqscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSeqscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESEQSCAN_H
+#define NODESEQSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate, int eflags);
+extern void ExecEndSeqScan(SeqScanState *node);
+extern void ExecReScanSeqScan(SeqScanState *node);
+
+/* parallel scan support */
+extern void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt);
+extern void ExecSeqScanInitializeDSM(SeqScanState *node, ParallelContext *pcxt);
+extern void ExecSeqScanReInitializeDSM(SeqScanState *node, ParallelContext *pcxt);
+extern void ExecSeqScanInitializeWorker(SeqScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+#endif /* NODESEQSCAN_H */
diff --git a/src/include/executor/nodeSetOp.h b/src/include/executor/nodeSetOp.h
new file mode 100644
index 0000000..d40ed74
--- /dev/null
+++ b/src/include/executor/nodeSetOp.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSetOp.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSetOp.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESETOP_H
+#define NODESETOP_H
+
+#include "nodes/execnodes.h"
+
+extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate, int eflags);
+extern void ExecEndSetOp(SetOpState *node);
+extern void ExecReScanSetOp(SetOpState *node);
+
+#endif /* NODESETOP_H */
diff --git a/src/include/executor/nodeSort.h b/src/include/executor/nodeSort.h
new file mode 100644
index 0000000..bf9a522
--- /dev/null
+++ b/src/include/executor/nodeSort.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSort.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSort.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESORT_H
+#define NODESORT_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern SortState *ExecInitSort(Sort *node, EState *estate, int eflags);
+extern void ExecEndSort(SortState *node);
+extern void ExecSortMarkPos(SortState *node);
+extern void ExecSortRestrPos(SortState *node);
+extern void ExecReScanSort(SortState *node);
+
+/* parallel instrumentation support */
+extern void ExecSortEstimate(SortState *node, ParallelContext *pcxt);
+extern void ExecSortInitializeDSM(SortState *node, ParallelContext *pcxt);
+extern void ExecSortInitializeWorker(SortState *node, ParallelWorkerContext *pwcxt);
+extern void ExecSortRetrieveInstrumentation(SortState *node);
+
+#endif /* NODESORT_H */
diff --git a/src/include/executor/nodeSubplan.h b/src/include/executor/nodeSubplan.h
new file mode 100644
index 0000000..df136cb
--- /dev/null
+++ b/src/include/executor/nodeSubplan.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSubplan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSubplan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESUBPLAN_H
+#define NODESUBPLAN_H
+
+#include "nodes/execnodes.h"
+
+extern SubPlanState *ExecInitSubPlan(SubPlan *subplan, PlanState *parent);
+
+extern Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull);
+
+extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
+
+extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
+
+extern void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext);
+
+#endif /* NODESUBPLAN_H */
diff --git a/src/include/executor/nodeSubqueryscan.h b/src/include/executor/nodeSubqueryscan.h
new file mode 100644
index 0000000..ded12a7
--- /dev/null
+++ b/src/include/executor/nodeSubqueryscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSubqueryscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSubqueryscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESUBQUERYSCAN_H
+#define NODESUBQUERYSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags);
+extern void ExecEndSubqueryScan(SubqueryScanState *node);
+extern void ExecReScanSubqueryScan(SubqueryScanState *node);
+
+#endif /* NODESUBQUERYSCAN_H */
diff --git a/src/include/executor/nodeTableFuncscan.h b/src/include/executor/nodeTableFuncscan.h
new file mode 100644
index 0000000..6b64e08
--- /dev/null
+++ b/src/include/executor/nodeTableFuncscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeTableFuncscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeTableFuncscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODETABLEFUNCSCAN_H
+#define NODETABLEFUNCSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern TableFuncScanState *ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags);
+extern void ExecEndTableFuncScan(TableFuncScanState *node);
+extern void ExecReScanTableFuncScan(TableFuncScanState *node);
+
+#endif /* NODETABLEFUNCSCAN_H */
diff --git a/src/include/executor/nodeTidrangescan.h b/src/include/executor/nodeTidrangescan.h
new file mode 100644
index 0000000..a57a47e
--- /dev/null
+++ b/src/include/executor/nodeTidrangescan.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeTidrangescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeTidrangescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODETIDRANGESCAN_H
+#define NODETIDRANGESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern TidRangeScanState *ExecInitTidRangeScan(TidRangeScan *node,
+ EState *estate, int eflags);
+extern void ExecEndTidRangeScan(TidRangeScanState *node);
+extern void ExecReScanTidRangeScan(TidRangeScanState *node);
+
+#endif /* NODETIDRANGESCAN_H */
diff --git a/src/include/executor/nodeTidscan.h b/src/include/executor/nodeTidscan.h
new file mode 100644
index 0000000..6be5ace
--- /dev/null
+++ b/src/include/executor/nodeTidscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeTidscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeTidscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODETIDSCAN_H
+#define NODETIDSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern TidScanState *ExecInitTidScan(TidScan *node, EState *estate, int eflags);
+extern void ExecEndTidScan(TidScanState *node);
+extern void ExecReScanTidScan(TidScanState *node);
+
+#endif /* NODETIDSCAN_H */
diff --git a/src/include/executor/nodeUnique.h b/src/include/executor/nodeUnique.h
new file mode 100644
index 0000000..1cde34f
--- /dev/null
+++ b/src/include/executor/nodeUnique.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeUnique.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeUnique.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEUNIQUE_H
+#define NODEUNIQUE_H
+
+#include "nodes/execnodes.h"
+
+extern UniqueState *ExecInitUnique(Unique *node, EState *estate, int eflags);
+extern void ExecEndUnique(UniqueState *node);
+extern void ExecReScanUnique(UniqueState *node);
+
+#endif /* NODEUNIQUE_H */
diff --git a/src/include/executor/nodeValuesscan.h b/src/include/executor/nodeValuesscan.h
new file mode 100644
index 0000000..1c2a461
--- /dev/null
+++ b/src/include/executor/nodeValuesscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeValuesscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeValuesscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEVALUESSCAN_H
+#define NODEVALUESSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern ValuesScanState *ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags);
+extern void ExecEndValuesScan(ValuesScanState *node);
+extern void ExecReScanValuesScan(ValuesScanState *node);
+
+#endif /* NODEVALUESSCAN_H */
diff --git a/src/include/executor/nodeWindowAgg.h b/src/include/executor/nodeWindowAgg.h
new file mode 100644
index 0000000..f64841c
--- /dev/null
+++ b/src/include/executor/nodeWindowAgg.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeWindowAgg.h
+ * prototypes for nodeWindowAgg.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeWindowAgg.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEWINDOWAGG_H
+#define NODEWINDOWAGG_H
+
+#include "nodes/execnodes.h"
+
+extern WindowAggState *ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags);
+extern void ExecEndWindowAgg(WindowAggState *node);
+extern void ExecReScanWindowAgg(WindowAggState *node);
+
+#endif /* NODEWINDOWAGG_H */
diff --git a/src/include/executor/nodeWorktablescan.h b/src/include/executor/nodeWorktablescan.h
new file mode 100644
index 0000000..998a731
--- /dev/null
+++ b/src/include/executor/nodeWorktablescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeWorktablescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeWorktablescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEWORKTABLESCAN_H
+#define NODEWORKTABLESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern WorkTableScanState *ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags);
+extern void ExecEndWorkTableScan(WorkTableScanState *node);
+extern void ExecReScanWorkTableScan(WorkTableScanState *node);
+
+#endif /* NODEWORKTABLESCAN_H */
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
new file mode 100644
index 0000000..1e66a7d
--- /dev/null
+++ b/src/include/executor/spi.h
@@ -0,0 +1,213 @@
+/*-------------------------------------------------------------------------
+ *
+ * spi.h
+ * Server Programming Interface public declarations
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/spi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPI_H
+#define SPI_H
+
+#include "commands/trigger.h"
+#include "lib/ilist.h"
+#include "parser/parser.h"
+#include "utils/portal.h"
+
+
+typedef struct SPITupleTable
+{
+ /* Public members */
+ TupleDesc tupdesc; /* tuple descriptor */
+ HeapTuple *vals; /* array of tuples */
+ uint64 numvals; /* number of valid tuples */
+
+ /* Private members, not intended for external callers */
+ uint64 alloced; /* allocated length of vals array */
+ MemoryContext tuptabcxt; /* memory context of result table */
+ slist_node next; /* link for internal bookkeeping */
+ SubTransactionId subid; /* subxact in which tuptable was created */
+} SPITupleTable;
+
+/* Optional arguments for SPI_prepare_extended */
+typedef struct SPIPrepareOptions
+{
+ ParserSetupHook parserSetup;
+ void *parserSetupArg;
+ RawParseMode parseMode;
+ int cursorOptions;
+} SPIPrepareOptions;
+
+/* Optional arguments for SPI_execute[_plan]_extended */
+typedef struct SPIExecuteOptions
+{
+ ParamListInfo params;
+ bool read_only;
+ bool allow_nonatomic;
+ bool must_return_tuples;
+ uint64 tcount;
+ DestReceiver *dest;
+ ResourceOwner owner;
+} SPIExecuteOptions;
+
+/* Optional arguments for SPI_cursor_parse_open */
+typedef struct SPIParseOpenOptions
+{
+ ParamListInfo params;
+ int cursorOptions;
+ bool read_only;
+} SPIParseOpenOptions;
+
+/* Plans are opaque structs for standard users of SPI */
+typedef struct _SPI_plan *SPIPlanPtr;
+
+#define SPI_ERROR_CONNECT (-1)
+#define SPI_ERROR_COPY (-2)
+#define SPI_ERROR_OPUNKNOWN (-3)
+#define SPI_ERROR_UNCONNECTED (-4)
+#define SPI_ERROR_CURSOR (-5) /* not used anymore */
+#define SPI_ERROR_ARGUMENT (-6)
+#define SPI_ERROR_PARAM (-7)
+#define SPI_ERROR_TRANSACTION (-8)
+#define SPI_ERROR_NOATTRIBUTE (-9)
+#define SPI_ERROR_NOOUTFUNC (-10)
+#define SPI_ERROR_TYPUNKNOWN (-11)
+#define SPI_ERROR_REL_DUPLICATE (-12)
+#define SPI_ERROR_REL_NOT_FOUND (-13)
+
+#define SPI_OK_CONNECT 1
+#define SPI_OK_FINISH 2
+#define SPI_OK_FETCH 3
+#define SPI_OK_UTILITY 4
+#define SPI_OK_SELECT 5
+#define SPI_OK_SELINTO 6
+#define SPI_OK_INSERT 7
+#define SPI_OK_DELETE 8
+#define SPI_OK_UPDATE 9
+#define SPI_OK_CURSOR 10
+#define SPI_OK_INSERT_RETURNING 11
+#define SPI_OK_DELETE_RETURNING 12
+#define SPI_OK_UPDATE_RETURNING 13
+#define SPI_OK_REWRITTEN 14
+#define SPI_OK_REL_REGISTER 15
+#define SPI_OK_REL_UNREGISTER 16
+#define SPI_OK_TD_REGISTER 17
+
+#define SPI_OPT_NONATOMIC (1 << 0)
+
+/* These used to be functions, now just no-ops for backwards compatibility */
+#define SPI_push() ((void) 0)
+#define SPI_pop() ((void) 0)
+#define SPI_push_conditional() false
+#define SPI_pop_conditional(pushed) ((void) 0)
+#define SPI_restore_connection() ((void) 0)
+
+extern PGDLLIMPORT uint64 SPI_processed;
+extern PGDLLIMPORT SPITupleTable *SPI_tuptable;
+extern PGDLLIMPORT int SPI_result;
+
+extern int SPI_connect(void);
+extern int SPI_connect_ext(int options);
+extern int SPI_finish(void);
+extern int SPI_execute(const char *src, bool read_only, long tcount);
+extern int SPI_execute_extended(const char *src,
+ const SPIExecuteOptions *options);
+extern int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+ bool read_only, long tcount);
+extern int SPI_execute_plan_extended(SPIPlanPtr plan,
+ const SPIExecuteOptions *options);
+extern int SPI_execute_plan_with_paramlist(SPIPlanPtr plan,
+ ParamListInfo params,
+ bool read_only, long tcount);
+extern int SPI_exec(const char *src, long tcount);
+extern int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+ long tcount);
+extern int SPI_execute_snapshot(SPIPlanPtr plan,
+ Datum *Values, const char *Nulls,
+ Snapshot snapshot,
+ Snapshot crosscheck_snapshot,
+ bool read_only, bool fire_triggers, long tcount);
+extern int SPI_execute_with_args(const char *src,
+ int nargs, Oid *argtypes,
+ Datum *Values, const char *Nulls,
+ bool read_only, long tcount);
+extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes);
+extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
+ int cursorOptions);
+extern SPIPlanPtr SPI_prepare_extended(const char *src,
+ const SPIPrepareOptions *options);
+extern SPIPlanPtr SPI_prepare_params(const char *src,
+ ParserSetupHook parserSetup,
+ void *parserSetupArg,
+ int cursorOptions);
+extern int SPI_keepplan(SPIPlanPtr plan);
+extern SPIPlanPtr SPI_saveplan(SPIPlanPtr plan);
+extern int SPI_freeplan(SPIPlanPtr plan);
+
+extern Oid SPI_getargtypeid(SPIPlanPtr plan, int argIndex);
+extern int SPI_getargcount(SPIPlanPtr plan);
+extern bool SPI_is_cursor_plan(SPIPlanPtr plan);
+extern bool SPI_plan_is_valid(SPIPlanPtr plan);
+extern const char *SPI_result_code_string(int code);
+
+extern List *SPI_plan_get_plan_sources(SPIPlanPtr plan);
+extern CachedPlan *SPI_plan_get_cached_plan(SPIPlanPtr plan);
+
+extern HeapTuple SPI_copytuple(HeapTuple tuple);
+extern HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc);
+extern HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts,
+ int *attnum, Datum *Values, const char *Nulls);
+extern int SPI_fnumber(TupleDesc tupdesc, const char *fname);
+extern char *SPI_fname(TupleDesc tupdesc, int fnumber);
+extern char *SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber);
+extern Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull);
+extern char *SPI_gettype(TupleDesc tupdesc, int fnumber);
+extern Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber);
+extern char *SPI_getrelname(Relation rel);
+extern char *SPI_getnspname(Relation rel);
+extern void *SPI_palloc(Size size);
+extern void *SPI_repalloc(void *pointer, Size size);
+extern void SPI_pfree(void *pointer);
+extern Datum SPI_datumTransfer(Datum value, bool typByVal, int typLen);
+extern void SPI_freetuple(HeapTuple pointer);
+extern void SPI_freetuptable(SPITupleTable *tuptable);
+
+extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan,
+ Datum *Values, const char *Nulls, bool read_only);
+extern Portal SPI_cursor_open_with_args(const char *name,
+ const char *src,
+ int nargs, Oid *argtypes,
+ Datum *Values, const char *Nulls,
+ bool read_only, int cursorOptions);
+extern Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan,
+ ParamListInfo params, bool read_only);
+extern Portal SPI_cursor_parse_open(const char *name,
+ const char *src,
+ const SPIParseOpenOptions *options);
+extern Portal SPI_cursor_find(const char *name);
+extern void SPI_cursor_fetch(Portal portal, bool forward, long count);
+extern void SPI_cursor_move(Portal portal, bool forward, long count);
+extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count);
+extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count);
+extern void SPI_cursor_close(Portal portal);
+
+extern int SPI_register_relation(EphemeralNamedRelation enr);
+extern int SPI_unregister_relation(const char *name);
+extern int SPI_register_trigger_data(TriggerData *tdata);
+
+extern void SPI_start_transaction(void);
+extern void SPI_commit(void);
+extern void SPI_commit_and_chain(void);
+extern void SPI_rollback(void);
+extern void SPI_rollback_and_chain(void);
+
+extern void SPICleanup(void);
+extern void AtEOXact_SPI(bool isCommit);
+extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);
+extern bool SPI_inside_nonatomic_context(void);
+
+#endif /* SPI_H */
diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h
new file mode 100644
index 0000000..97f4279
--- /dev/null
+++ b/src/include/executor/spi_priv.h
@@ -0,0 +1,105 @@
+/*-------------------------------------------------------------------------
+ *
+ * spi_priv.h
+ * Server Programming Interface private declarations
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/spi_priv.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPI_PRIV_H
+#define SPI_PRIV_H
+
+#include "executor/spi.h"
+#include "utils/queryenvironment.h"
+
+
+#define _SPI_PLAN_MAGIC 569278163
+
+typedef struct
+{
+ /* current results */
+ uint64 processed; /* by Executor */
+ SPITupleTable *tuptable; /* tuptable currently being built */
+
+ /* subtransaction in which current Executor call was started */
+ SubTransactionId execSubid;
+
+ /* resources of this execution context */
+ slist_head tuptables; /* list of all live SPITupleTables */
+ MemoryContext procCxt; /* procedure context */
+ MemoryContext execCxt; /* executor context */
+ MemoryContext savedcxt; /* context of SPI_connect's caller */
+ SubTransactionId connectSubid; /* ID of connecting subtransaction */
+ QueryEnvironment *queryEnv; /* query environment setup for SPI level */
+
+ /* transaction management support */
+ bool atomic; /* atomic execution context, does not allow
+ * transactions */
+ bool internal_xact; /* SPI-managed transaction boundary, skip
+ * cleanup */
+
+ /* saved values of API global variables for previous nesting level */
+ uint64 outer_processed;
+ SPITupleTable *outer_tuptable;
+ int outer_result;
+} _SPI_connection;
+
+/*
+ * SPI plans have three states: saved, unsaved, or temporary.
+ *
+ * Ordinarily, the _SPI_plan struct itself as well as the argtypes array
+ * are in a dedicated memory context identified by plancxt (which can be
+ * really small). All the other subsidiary state is in plancache entries
+ * identified by plancache_list (note: the list cells themselves are in
+ * plancxt).
+ *
+ * In an unsaved plan, the plancxt as well as the plancache entries' contexts
+ * are children of the SPI procedure context, so they'll all disappear at
+ * function exit. plancache.c also knows that the plancache entries are
+ * "unsaved", so it doesn't link them into its global list; hence they do
+ * not respond to inval events. This is OK since we are presumably holding
+ * adequate locks to prevent other backends from messing with the tables.
+ *
+ * For a saved plan, the plancxt is made a child of CacheMemoryContext
+ * since it should persist until explicitly destroyed. Likewise, the
+ * plancache entries will be under CacheMemoryContext since we tell
+ * plancache.c to save them. We rely on plancache.c to keep the cache
+ * entries up-to-date as needed in the face of invalidation events.
+ *
+ * There are also "temporary" SPI plans, in which the _SPI_plan struct is
+ * not even palloc'd but just exists in some function's local variable.
+ * The plancache entries are unsaved and exist under the SPI executor context,
+ * while additional data such as argtypes and list cells is loose in the SPI
+ * executor context. Such plans can be identified by having plancxt == NULL.
+ *
+ * We can also have "one-shot" SPI plans (which are typically temporary,
+ * as described above). These are meant to be executed once and discarded,
+ * and various optimizations are made on the assumption of single use.
+ * Note in particular that the CachedPlanSources within such an SPI plan
+ * are not "complete" until execution.
+ *
+ * Note: if the original query string contained only whitespace and comments,
+ * the plancache_list will be NIL and so there is no place to store the
+ * query string. We don't care about that, but we do care about the
+ * argument type array, which is why it's seemingly-redundantly stored.
+ */
+typedef struct _SPI_plan
+{
+ int magic; /* should equal _SPI_PLAN_MAGIC */
+ bool saved; /* saved or unsaved plan? */
+ bool oneshot; /* one-shot plan? */
+ List *plancache_list; /* one CachedPlanSource per parsetree */
+ MemoryContext plancxt; /* Context containing _SPI_plan and data */
+ RawParseMode parse_mode; /* raw_parser() mode */
+ int cursor_options; /* Cursor options used for planning */
+ int nargs; /* number of plan arguments */
+ Oid *argtypes; /* Argument types (NULL if nargs is 0) */
+ ParserSetupHook parserSetup; /* alternative parameter spec method */
+ void *parserSetupArg;
+} _SPI_plan;
+
+#endif /* SPI_PRIV_H */
diff --git a/src/include/executor/tablefunc.h b/src/include/executor/tablefunc.h
new file mode 100644
index 0000000..17626b0
--- /dev/null
+++ b/src/include/executor/tablefunc.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * tablefunc.h
+ * interface for TableFunc executor node
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tablefunc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _TABLEFUNC_H
+#define _TABLEFUNC_H
+
+/* Forward-declare this to avoid including execnodes.h here */
+struct TableFuncScanState;
+
+/*
+ * TableFuncRoutine holds function pointers used for generating content of
+ * table-producer functions, such as XMLTABLE.
+ *
+ * InitOpaque initializes table builder private objects. The output tuple
+ * descriptor, input functions for the columns, and typioparams are passed
+ * from executor state.
+ *
+ * SetDocument is called to define the input document. The table builder may
+ * apply additional transformations not exposed outside the table builder
+ * context.
+ *
+ * SetNamespace is called to pass namespace declarations from the table
+ * expression. This function may be NULL if namespaces are not supported by
+ * the table builder. Namespaces must be given before setting the row and
+ * column filters. If the name is given as NULL, the entry shall be for the
+ * default namespace.
+ *
+ * SetRowFilter is called do define the row-generating filter, which shall be
+ * used to extract each row from the input document.
+ *
+ * SetColumnFilter is called once for each column, to define the column-
+ * generating filter for the given column.
+ *
+ * FetchRow shall be called repeatedly until it returns that no more rows are
+ * found in the document. On each invocation it shall set state in the table
+ * builder context such that each subsequent GetValue call returns the values
+ * for the indicated column for the row being processed.
+ *
+ * DestroyOpaque shall release all resources associated with a table builder
+ * context. It may be called either because all rows have been consumed, or
+ * because an error occurred while processing the table expression.
+ */
+typedef struct TableFuncRoutine
+{
+ void (*InitOpaque) (struct TableFuncScanState *state, int natts);
+ void (*SetDocument) (struct TableFuncScanState *state, Datum value);
+ void (*SetNamespace) (struct TableFuncScanState *state, const char *name,
+ const char *uri);
+ void (*SetRowFilter) (struct TableFuncScanState *state, const char *path);
+ void (*SetColumnFilter) (struct TableFuncScanState *state,
+ const char *path, int colnum);
+ bool (*FetchRow) (struct TableFuncScanState *state);
+ Datum (*GetValue) (struct TableFuncScanState *state, int colnum,
+ Oid typid, int32 typmod, bool *isnull);
+ void (*DestroyOpaque) (struct TableFuncScanState *state);
+} TableFuncRoutine;
+
+#endif /* _TABLEFUNC_H */
diff --git a/src/include/executor/tqueue.h b/src/include/executor/tqueue.h
new file mode 100644
index 0000000..ed470f0
--- /dev/null
+++ b/src/include/executor/tqueue.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * tqueue.h
+ * Use shm_mq to send & receive tuples between parallel backends
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tqueue.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef TQUEUE_H
+#define TQUEUE_H
+
+#include "storage/shm_mq.h"
+#include "tcop/dest.h"
+
+/* Opaque struct, only known inside tqueue.c. */
+typedef struct TupleQueueReader TupleQueueReader;
+
+/* Use this to send tuples to a shm_mq. */
+extern DestReceiver *CreateTupleQueueDestReceiver(shm_mq_handle *handle);
+
+/* Use these to receive tuples from a shm_mq. */
+extern TupleQueueReader *CreateTupleQueueReader(shm_mq_handle *handle);
+extern void DestroyTupleQueueReader(TupleQueueReader *reader);
+extern MinimalTuple TupleQueueReaderNext(TupleQueueReader *reader,
+ bool nowait, bool *done);
+
+#endif /* TQUEUE_H */
diff --git a/src/include/executor/tstoreReceiver.h b/src/include/executor/tstoreReceiver.h
new file mode 100644
index 0000000..1f58b4f
--- /dev/null
+++ b/src/include/executor/tstoreReceiver.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * tstoreReceiver.h
+ * prototypes for tstoreReceiver.c
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tstoreReceiver.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef TSTORE_RECEIVER_H
+#define TSTORE_RECEIVER_H
+
+#include "tcop/dest.h"
+#include "utils/tuplestore.h"
+
+
+extern DestReceiver *CreateTuplestoreDestReceiver(void);
+
+extern void SetTuplestoreDestReceiverParams(DestReceiver *self,
+ Tuplestorestate *tStore,
+ MemoryContext tContext,
+ bool detoast,
+ TupleDesc target_tupdesc,
+ const char *map_failure_msg);
+
+#endif /* TSTORE_RECEIVER_H */
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
new file mode 100644
index 0000000..679e57f
--- /dev/null
+++ b/src/include/executor/tuptable.h
@@ -0,0 +1,487 @@
+/*-------------------------------------------------------------------------
+ *
+ * tuptable.h
+ * tuple table support stuff
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tuptable.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TUPTABLE_H
+#define TUPTABLE_H
+
+#include "access/htup.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/tupdesc.h"
+#include "storage/buf.h"
+
+/*----------
+ * The executor stores tuples in a "tuple table" which is a List of
+ * independent TupleTableSlots.
+ *
+ * There's various different types of tuple table slots, each being able to
+ * store different types of tuples. Additional types of slots can be added
+ * without modifying core code. The type of a slot is determined by the
+ * TupleTableSlotOps* passed to the slot creation routine. The builtin types
+ * of slots are
+ *
+ * 1. physical tuple in a disk buffer page (TTSOpsBufferHeapTuple)
+ * 2. physical tuple constructed in palloc'ed memory (TTSOpsHeapTuple)
+ * 3. "minimal" physical tuple constructed in palloc'ed memory
+ * (TTSOpsMinimalTuple)
+ * 4. "virtual" tuple consisting of Datum/isnull arrays (TTSOpsVirtual)
+ *
+ *
+ * The first two cases are similar in that they both deal with "materialized"
+ * tuples, but resource management is different. For a tuple in a disk page
+ * we need to hold a pin on the buffer until the TupleTableSlot's reference
+ * to the tuple is dropped; while for a palloc'd tuple we usually want the
+ * tuple pfree'd when the TupleTableSlot's reference is dropped.
+ *
+ * A "minimal" tuple is handled similarly to a palloc'd regular tuple.
+ * At present, minimal tuples never are stored in buffers, so there is no
+ * parallel to case 1. Note that a minimal tuple has no "system columns".
+ * (Actually, it could have an OID, but we have no need to access the OID.)
+ *
+ * A "virtual" tuple is an optimization used to minimize physical data copying
+ * in a nest of plan nodes. Until materialized pass-by-reference Datums in
+ * the slot point to storage that is not directly associated with the
+ * TupleTableSlot; generally they will point to part of a tuple stored in a
+ * lower plan node's output TupleTableSlot, or to a function result
+ * constructed in a plan node's per-tuple econtext. It is the responsibility
+ * of the generating plan node to be sure these resources are not released for
+ * as long as the virtual tuple needs to be valid or is materialized. Note
+ * also that a virtual tuple does not have any "system columns".
+ *
+ * The Datum/isnull arrays of a TupleTableSlot serve double duty. For virtual
+ * slots they are the authoritative data. For the other builtin slots,
+ * the arrays contain data extracted from the tuple. (In this state, any
+ * pass-by-reference Datums point into the physical tuple.) The extracted
+ * information is built "lazily", ie, only as needed. This serves to avoid
+ * repeated extraction of data from the physical tuple.
+ *
+ * A TupleTableSlot can also be "empty", indicated by flag TTS_FLAG_EMPTY set
+ * in tts_flags, holding no valid data. This is the only valid state for a
+ * freshly-created slot that has not yet had a tuple descriptor assigned to
+ * it. In this state, TTS_SHOULDFREE should not be set in tts_flags, tts_tuple
+ * must be NULL and tts_nvalid zero.
+ *
+ * The tupleDescriptor is simply referenced, not copied, by the TupleTableSlot
+ * code. The caller of ExecSetSlotDescriptor() is responsible for providing
+ * a descriptor that will live as long as the slot does. (Typically, both
+ * slots and descriptors are in per-query memory and are freed by memory
+ * context deallocation at query end; so it's not worth providing any extra
+ * mechanism to do more. However, the slot will increment the tupdesc
+ * reference count if a reference-counted tupdesc is supplied.)
+ *
+ * When TTS_SHOULDFREE is set in tts_flags, the physical tuple is "owned" by
+ * the slot and should be freed when the slot's reference to the tuple is
+ * dropped.
+ *
+ * tts_values/tts_isnull are allocated either when the slot is created (when
+ * the descriptor is provided), or when a descriptor is assigned to the slot;
+ * they are of length equal to the descriptor's natts.
+ *
+ * The TTS_FLAG_SLOW flag is saved state for
+ * slot_deform_heap_tuple, and should not be touched by any other code.
+ *----------
+ */
+
+/* true = slot is empty */
+#define TTS_FLAG_EMPTY (1 << 1)
+#define TTS_EMPTY(slot) (((slot)->tts_flags & TTS_FLAG_EMPTY) != 0)
+
+/* should pfree tuple "owned" by the slot? */
+#define TTS_FLAG_SHOULDFREE (1 << 2)
+#define TTS_SHOULDFREE(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREE) != 0)
+
+/* saved state for slot_deform_heap_tuple */
+#define TTS_FLAG_SLOW (1 << 3)
+#define TTS_SLOW(slot) (((slot)->tts_flags & TTS_FLAG_SLOW) != 0)
+
+/* fixed tuple descriptor */
+#define TTS_FLAG_FIXED (1 << 4)
+#define TTS_FIXED(slot) (((slot)->tts_flags & TTS_FLAG_FIXED) != 0)
+
+struct TupleTableSlotOps;
+typedef struct TupleTableSlotOps TupleTableSlotOps;
+
+/* base tuple table slot type */
+typedef struct TupleTableSlot
+{
+ NodeTag type;
+#define FIELDNO_TUPLETABLESLOT_FLAGS 1
+ uint16 tts_flags; /* Boolean states */
+#define FIELDNO_TUPLETABLESLOT_NVALID 2
+ AttrNumber tts_nvalid; /* # of valid values in tts_values */
+ const TupleTableSlotOps *const tts_ops; /* implementation of slot */
+#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
+ TupleDesc tts_tupleDescriptor; /* slot's tuple descriptor */
+#define FIELDNO_TUPLETABLESLOT_VALUES 5
+ Datum *tts_values; /* current per-attribute values */
+#define FIELDNO_TUPLETABLESLOT_ISNULL 6
+ bool *tts_isnull; /* current per-attribute isnull flags */
+ MemoryContext tts_mcxt; /* slot itself is in this context */
+ ItemPointerData tts_tid; /* stored tuple's tid */
+ Oid tts_tableOid; /* table oid of tuple */
+} TupleTableSlot;
+
+/* routines for a TupleTableSlot implementation */
+struct TupleTableSlotOps
+{
+ /* Minimum size of the slot */
+ size_t base_slot_size;
+
+ /* Initialization. */
+ void (*init) (TupleTableSlot *slot);
+
+ /* Destruction. */
+ void (*release) (TupleTableSlot *slot);
+
+ /*
+ * Clear the contents of the slot. Only the contents are expected to be
+ * cleared and not the tuple descriptor. Typically an implementation of
+ * this callback should free the memory allocated for the tuple contained
+ * in the slot.
+ */
+ void (*clear) (TupleTableSlot *slot);
+
+ /*
+ * Fill up first natts entries of tts_values and tts_isnull arrays with
+ * values from the tuple contained in the slot. The function may be called
+ * with natts more than the number of attributes available in the tuple,
+ * in which case it should set tts_nvalid to the number of returned
+ * columns.
+ */
+ void (*getsomeattrs) (TupleTableSlot *slot, int natts);
+
+ /*
+ * Returns value of the given system attribute as a datum and sets isnull
+ * to false, if it's not NULL. Throws an error if the slot type does not
+ * support system attributes.
+ */
+ Datum (*getsysattr) (TupleTableSlot *slot, int attnum, bool *isnull);
+
+ /*
+ * Make the contents of the slot solely depend on the slot, and not on
+ * underlying resources (like another memory context, buffers, etc).
+ */
+ void (*materialize) (TupleTableSlot *slot);
+
+ /*
+ * Copy the contents of the source slot into the destination slot's own
+ * context. Invoked using callback of the destination slot.
+ */
+ void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
+
+ /*
+ * Return a heap tuple "owned" by the slot. It is slot's responsibility to
+ * free the memory consumed by the heap tuple. If the slot can not "own" a
+ * heap tuple, it should not implement this callback and should set it as
+ * NULL.
+ */
+ HeapTuple (*get_heap_tuple) (TupleTableSlot *slot);
+
+ /*
+ * Return a minimal tuple "owned" by the slot. It is slot's responsibility
+ * to free the memory consumed by the minimal tuple. If the slot can not
+ * "own" a minimal tuple, it should not implement this callback and should
+ * set it as NULL.
+ */
+ MinimalTuple (*get_minimal_tuple) (TupleTableSlot *slot);
+
+ /*
+ * Return a copy of heap tuple representing the contents of the slot. The
+ * copy needs to be palloc'd in the current memory context. The slot
+ * itself is expected to remain unaffected. It is *not* expected to have
+ * meaningful "system columns" in the copy. The copy is not be "owned" by
+ * the slot i.e. the caller has to take responsibility to free memory
+ * consumed by the slot.
+ */
+ HeapTuple (*copy_heap_tuple) (TupleTableSlot *slot);
+
+ /*
+ * Return a copy of minimal tuple representing the contents of the slot.
+ * The copy needs to be palloc'd in the current memory context. The slot
+ * itself is expected to remain unaffected. It is *not* expected to have
+ * meaningful "system columns" in the copy. The copy is not be "owned" by
+ * the slot i.e. the caller has to take responsibility to free memory
+ * consumed by the slot.
+ */
+ MinimalTuple (*copy_minimal_tuple) (TupleTableSlot *slot);
+};
+
+/*
+ * Predefined TupleTableSlotOps for various types of TupleTableSlotOps. The
+ * same are used to identify the type of a given slot.
+ */
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsVirtual;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsHeapTuple;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsMinimalTuple;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsBufferHeapTuple;
+
+#define TTS_IS_VIRTUAL(slot) ((slot)->tts_ops == &TTSOpsVirtual)
+#define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_ops == &TTSOpsHeapTuple)
+#define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_ops == &TTSOpsMinimalTuple)
+#define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_ops == &TTSOpsBufferHeapTuple)
+
+
+/*
+ * Tuple table slot implementations.
+ */
+
+typedef struct VirtualTupleTableSlot
+{
+ TupleTableSlot base;
+
+ char *data; /* data for materialized slots */
+} VirtualTupleTableSlot;
+
+typedef struct HeapTupleTableSlot
+{
+ TupleTableSlot base;
+
+#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE 1
+ HeapTuple tuple; /* physical tuple */
+#define FIELDNO_HEAPTUPLETABLESLOT_OFF 2
+ uint32 off; /* saved state for slot_deform_heap_tuple */
+ HeapTupleData tupdata; /* optional workspace for storing tuple */
+} HeapTupleTableSlot;
+
+/* heap tuple residing in a buffer */
+typedef struct BufferHeapTupleTableSlot
+{
+ HeapTupleTableSlot base;
+
+ /*
+ * If buffer is not InvalidBuffer, then the slot is holding a pin on the
+ * indicated buffer page; drop the pin when we release the slot's
+ * reference to that buffer. (TTS_FLAG_SHOULDFREE should not be set in
+ * such a case, since presumably tts_tuple is pointing into the buffer.)
+ */
+ Buffer buffer; /* tuple's buffer, or InvalidBuffer */
+} BufferHeapTupleTableSlot;
+
+typedef struct MinimalTupleTableSlot
+{
+ TupleTableSlot base;
+
+ /*
+ * In a minimal slot tuple points at minhdr and the fields of that struct
+ * are set correctly for access to the minimal tuple; in particular,
+ * minhdr.t_data points MINIMAL_TUPLE_OFFSET bytes before mintuple. This
+ * allows column extraction to treat the case identically to regular
+ * physical tuples.
+ */
+#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE 1
+ HeapTuple tuple; /* tuple wrapper */
+ MinimalTuple mintuple; /* minimal tuple, or NULL if none */
+ HeapTupleData minhdr; /* workspace for minimal-tuple-only case */
+#define FIELDNO_MINIMALTUPLETABLESLOT_OFF 4
+ uint32 off; /* saved state for slot_deform_heap_tuple */
+} MinimalTupleTableSlot;
+
+/*
+ * TupIsNull -- is a TupleTableSlot empty?
+ */
+#define TupIsNull(slot) \
+ ((slot) == NULL || TTS_EMPTY(slot))
+
+/* in executor/execTuples.c */
+extern TupleTableSlot *MakeTupleTableSlot(TupleDesc tupleDesc,
+ const TupleTableSlotOps *tts_ops);
+extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
+extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
+extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
+extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ bool shouldFree);
+extern void ExecForceStoreHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ bool shouldFree);
+extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ Buffer buffer);
+extern TupleTableSlot *ExecStorePinnedBufferHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ Buffer buffer);
+extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
+ TupleTableSlot *slot,
+ bool shouldFree);
+extern void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot,
+ bool shouldFree);
+extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
+extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
+extern void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot);
+extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree);
+extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
+ bool *shouldFree);
+extern Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot);
+extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
+ int lastAttNum);
+extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum);
+
+
+#ifndef FRONTEND
+
+/*
+ * This function forces the entries of the slot's Datum/isnull arrays to be
+ * valid at least up through the attnum'th entry.
+ */
+static inline void
+slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+{
+ if (slot->tts_nvalid < attnum)
+ slot_getsomeattrs_int(slot, attnum);
+}
+
+/*
+ * slot_getallattrs
+ * This function forces all the entries of the slot's Datum/isnull
+ * arrays to be valid. The caller may then extract data directly
+ * from those arrays instead of using slot_getattr.
+ */
+static inline void
+slot_getallattrs(TupleTableSlot *slot)
+{
+ slot_getsomeattrs(slot, slot->tts_tupleDescriptor->natts);
+}
+
+
+/*
+ * slot_attisnull
+ *
+ * Detect whether an attribute of the slot is null, without actually fetching
+ * it.
+ */
+static inline bool
+slot_attisnull(TupleTableSlot *slot, int attnum)
+{
+ AssertArg(attnum > 0);
+
+ if (attnum > slot->tts_nvalid)
+ slot_getsomeattrs(slot, attnum);
+
+ return slot->tts_isnull[attnum - 1];
+}
+
+/*
+ * slot_getattr - fetch one attribute of the slot's contents.
+ */
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum,
+ bool *isnull)
+{
+ AssertArg(attnum > 0);
+
+ if (attnum > slot->tts_nvalid)
+ slot_getsomeattrs(slot, attnum);
+
+ *isnull = slot->tts_isnull[attnum - 1];
+
+ return slot->tts_values[attnum - 1];
+}
+
+/*
+ * slot_getsysattr - fetch a system attribute of the slot's current tuple.
+ *
+ * If the slot type does not contain system attributes, this will throw an
+ * error. Hence before calling this function, callers should make sure that
+ * the slot type is the one that supports system attributes.
+ */
+static inline Datum
+slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ AssertArg(attnum < 0); /* caller error */
+
+ if (attnum == TableOidAttributeNumber)
+ {
+ *isnull = false;
+ return ObjectIdGetDatum(slot->tts_tableOid);
+ }
+ else if (attnum == SelfItemPointerAttributeNumber)
+ {
+ *isnull = false;
+ return PointerGetDatum(&slot->tts_tid);
+ }
+
+ /* Fetch the system attribute from the underlying tuple. */
+ return slot->tts_ops->getsysattr(slot, attnum, isnull);
+}
+
+/*
+ * ExecClearTuple - clear the slot's contents
+ */
+static inline TupleTableSlot *
+ExecClearTuple(TupleTableSlot *slot)
+{
+ slot->tts_ops->clear(slot);
+
+ return slot;
+}
+
+/* ExecMaterializeSlot - force a slot into the "materialized" state.
+ *
+ * This causes the slot's tuple to be a local copy not dependent on any
+ * external storage (i.e. pointing into a Buffer, or having allocations in
+ * another memory context).
+ *
+ * A typical use for this operation is to prepare a computed tuple for being
+ * stored on disk. The original data may or may not be virtual, but in any
+ * case we need a private copy for heap_insert to scribble on.
+ */
+static inline void
+ExecMaterializeSlot(TupleTableSlot *slot)
+{
+ slot->tts_ops->materialize(slot);
+}
+
+/*
+ * ExecCopySlotHeapTuple - return HeapTuple allocated in caller's context
+ */
+static inline HeapTuple
+ExecCopySlotHeapTuple(TupleTableSlot *slot)
+{
+ Assert(!TTS_EMPTY(slot));
+
+ return slot->tts_ops->copy_heap_tuple(slot);
+}
+
+/*
+ * ExecCopySlotMinimalTuple - return MinimalTuple allocated in caller's context
+ */
+static inline MinimalTuple
+ExecCopySlotMinimalTuple(TupleTableSlot *slot)
+{
+ return slot->tts_ops->copy_minimal_tuple(slot);
+}
+
+/*
+ * ExecCopySlot - copy one slot's contents into another.
+ *
+ * If a source's system attributes are supposed to be accessed in the target
+ * slot, the target slot and source slot types need to match.
+ */
+static inline TupleTableSlot *
+ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+ Assert(!TTS_EMPTY(srcslot));
+ AssertArg(srcslot != dstslot);
+
+ dstslot->tts_ops->copyslot(dstslot, srcslot);
+
+ return dstslot;
+}
+
+#endif /* FRONTEND */
+
+#endif /* TUPTABLE_H */