diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:19:15 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:19:15 +0000 |
commit | 6eb9c5a5657d1fe77b55cc261450f3538d35a94d (patch) | |
tree | 657d8194422a5daccecfd42d654b8a245ef7b4c8 /src/include/executor | |
parent | Initial commit. (diff) | |
download | postgresql-13-upstream.tar.xz postgresql-13-upstream.zip |
Adding upstream version 13.4.upstream/13.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/include/executor')
56 files changed, 4639 insertions, 0 deletions
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h new file mode 100644 index 0000000..afbab95 --- /dev/null +++ b/src/include/executor/execExpr.h @@ -0,0 +1,768 @@ +/*------------------------------------------------------------------------- + * + * execExpr.h + * Low level infrastructure related to expression evaluation + * + * + * Portions Copyright (c) 1996-2020, 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; + +/* 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); + +/* 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 a container subscript; short-circuit expression to NULL if NULL */ + EEOP_SBSREF_SUBSCRIPT, + + /* + * 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_XMLEXPR, + EEOP_AGGREF, + EEOP_GROUPING_FUNC, + EEOP_WINDOW_FUNC, + EEOP_SUBPLAN, + EEOP_ALTERNATIVE_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_SUBSCRIPT */ + struct + { + /* too big to have inline */ + struct SubscriptingRefState *state; + int off; /* 0-based index of this subscript */ + bool isupper; /* is it upper or lower subscript? */ + int jumpdone; /* jump here on null */ + } sbsref_subscript; + + /* for EEOP_SBSREF_OLD / ASSIGN / FETCH */ + struct + { + /* 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_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 + { + /* out-of-line state, modified by nodeAgg.c */ + AggrefExprState *astate; + } 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_ALTERNATIVE_SUBPLAN */ + struct + { + /* out-of-line state, created by nodeSubplan.c */ + AlternativeSubPlanState *asstate; + } alternative_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? */ + + Oid refelemtype; /* OID of the container element type */ + int16 refattrlength; /* typlen of container type */ + int16 refelemlength; /* typlen of the container element type */ + bool refelembyval; /* is the element type pass-by-value? */ + char refelemalign; /* typalign of the element type */ + + /* numupper and upperprovided[] are filled at compile time */ + /* at runtime, extracted subscript datums get stored in upperindex[] */ + int numupper; + bool upperprovided[MAXDIM]; + int upperindex[MAXDIM]; + + /* similarly for lower indexes, if any */ + int numlower; + bool lowerprovided[MAXDIM]; + int lowerindex[MAXDIM]; + + /* subscript expressions get evaluated into here */ + Datum subscriptvalue; + bool subscriptnull; + + /* for assignment, new value to assign is evaluated into here */ + Datum replacevalue; + bool replacenull; + + /* if we have a nested assignment, SBSREF_OLD puts old value here */ + Datum prevvalue; + bool prevnull; +} SubscriptingRefState; + + +/* 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 bool ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op); +extern void ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op); +extern void ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op); +extern void ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op); +extern void ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, + ExprContext *econtext); +extern void ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op); +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 ExecEvalAlternativeSubPlan(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..5a39a5b --- /dev/null +++ b/src/include/executor/execParallel.h @@ -0,0 +1,51 @@ +/*-------------------------------------------------------------------- + * execParallel.h + * POSTGRES parallel execution interface + * + * Portions Copyright (c) 1996-2020, 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..6d1b722 --- /dev/null +++ b/src/include/executor/execPartition.h @@ -0,0 +1,156 @@ +/*-------------------------------------------------------------------- + * execPartition.h + * POSTGRES partitioning executor interface + * + * Portions Copyright (c) 1996-2020, 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; + +/* + * PartitionRoutingInfo + * + * Additional result relation information specific to routing tuples to a + * table partition. + */ +typedef struct PartitionRoutingInfo +{ + /* + * Map for converting tuples in root partitioned table format into + * partition format, or NULL if no conversion is required. + */ + TupleConversionMap *pi_RootToPartitionMap; + + /* + * Map for converting tuples in partition format into the root partitioned + * table format, or NULL if no conversion is required. + */ + TupleConversionMap *pi_PartitionToRootMap; + + /* + * Slot to store tuples in partition format, or NULL when no translation + * is required between root and partition. + */ + TupleTableSlot *pi_PartitionTupleSlot; +} PartitionRoutingInfo; + +/* + * 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, + ModifyTableState *mtstate, + 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..4af6e00 --- /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-2020, 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..b5cead3 --- /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-2020, 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..18f834f --- /dev/null +++ b/src/include/executor/executor.h @@ -0,0 +1,620 @@ +/*------------------------------------------------------------------------- + * + * executor.h + * support for the POSTGRES executor module + * + * + * Portions Copyright (c) 1996-2020, 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 *ExecInitJunkFilterInsertion(List *targetList, + TupleDesc cleanTupType, + 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 Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, + bool *isNull); +extern TupleTableSlot *ExecFilterJunk(JunkFilter *junkfilter, + TupleTableSlot *slot); + + +/* + * 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 ExecCleanUpTriggerState(EState *estate); +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 ProjectionInfo *ExecBuildProjectionInfo(List *targetList, + ExprContext *econtext, + TupleTableSlot *slot, + PlanState *parent, + TupleDesc inputDesc); +extern ProjectionInfo *ExecBuildProjectionInfoExt(List *targetList, + ExprContext *econtext, + TupleTableSlot *slot, + bool assignJunkEntries, + PlanState *parent, + TupleDesc inputDesc); +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); + +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 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 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(TupleTableSlot *slot, EState *estate, bool noDupErr, + bool *specConflict, List *arbiterIndexes); +extern bool ExecCheckIndexConstraints(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(EState *estate, TupleTableSlot *slot); +extern void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, + TupleTableSlot *searchslot, TupleTableSlot *slot); +extern void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, + TupleTableSlot *searchslot); +extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd); + +extern void CheckSubscriptionRelkind(char relkind, const char *nspname, + const char *relname); + +#endif /* EXECUTOR_H */ diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h new file mode 100644 index 0000000..a0db24b --- /dev/null +++ b/src/include/executor/functions.h @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------------- + * + * functions.h + * Declarations for execution of SQL-language functions. + * + * + * Portions Copyright (c) 1996-2020, 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" + +/* This struct is known only within executor/functions.c */ +typedef struct 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..eb5daba --- /dev/null +++ b/src/include/executor/hashjoin.h @@ -0,0 +1,362 @@ +/*------------------------------------------------------------------------- + * + * hashjoin.h + * internal structures for hash joins + * + * + * Portions Copyright (c) 1996-2020, 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..a97562e --- /dev/null +++ b/src/include/executor/instrument.h @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------- + * + * instrument.h + * definitions for run-time statistics collection + * + * + * Copyright (c) 2001-2020, PostgreSQL Global Development Group + * + * src/include/executor/instrument.h + * + *------------------------------------------------------------------------- + */ +#ifndef INSTRUMENT_H +#define INSTRUMENT_H + +#include "portability/instr_time.h" + + +typedef struct BufferUsage +{ + long shared_blks_hit; /* # of shared buffer hits */ + long shared_blks_read; /* # of shared disk blocks read */ + long shared_blks_dirtied; /* # of shared blocks dirtied */ + long shared_blks_written; /* # of shared disk blocks written */ + long local_blks_hit; /* # of local buffer hits */ + long local_blks_read; /* # of local disk blocks read */ + long local_blks_dirtied; /* # of shared blocks dirtied */ + long local_blks_written; /* # of local disk blocks written */ + long temp_blks_read; /* # of temp blocks read */ + long temp_blks_written; /* # of temp blocks written */ + instr_time blk_read_time; /* time spent reading */ + instr_time blk_write_time; /* time spent writing */ +} BufferUsage; + +typedef struct WalUsage +{ + long wal_records; /* # of WAL records produced */ + long 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 */ + /* 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); +extern void InstrInit(Instrumentation *instr, int instrument_options); +extern void InstrStartNode(Instrumentation *instr); +extern void InstrStopNode(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..b955169 --- /dev/null +++ b/src/include/executor/nodeAgg.h @@ -0,0 +1,333 @@ +/*------------------------------------------------------------------------- + * + * nodeAgg.h + * prototypes for nodeAgg.c + * + * + * Portions Copyright (c) 1996-2020, 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..be222eb --- /dev/null +++ b/src/include/executor/nodeAppend.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * nodeAppend.h + * + * + * + * Portions Copyright (c) 1996-2020, 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); + +#endif /* NODEAPPEND_H */ diff --git a/src/include/executor/nodeBitmapAnd.h b/src/include/executor/nodeBitmapAnd.h new file mode 100644 index 0000000..2271bb7 --- /dev/null +++ b/src/include/executor/nodeBitmapAnd.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * nodeBitmapAnd.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..10228af --- /dev/null +++ b/src/include/executor/nodeBitmapHeapscan.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * nodeBitmapHeapscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..42a24e6 --- /dev/null +++ b/src/include/executor/nodeBitmapIndexscan.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * nodeBitmapIndexscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..58a7b8c --- /dev/null +++ b/src/include/executor/nodeBitmapOr.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * nodeBitmapOr.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..3e75552 --- /dev/null +++ b/src/include/executor/nodeCtescan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeCtescan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..1d52875 --- /dev/null +++ b/src/include/executor/nodeCustom.h @@ -0,0 +1,42 @@ +/* ------------------------------------------------------------------------ + * + * nodeCustom.h + * + * prototypes for CustomScan nodes + * + * Portions Copyright (c) 1996-2020, 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..326d713 --- /dev/null +++ b/src/include/executor/nodeForeignscan.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------- + * + * nodeForeignscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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); + +#endif /* NODEFOREIGNSCAN_H */ diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h new file mode 100644 index 0000000..74e8eef --- /dev/null +++ b/src/include/executor/nodeFunctionscan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeFunctionscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..105248b --- /dev/null +++ b/src/include/executor/nodeGather.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * nodeGather.h + * prototypes for nodeGather.c + * + * + * Portions Copyright (c) 1996-2020, 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..a8f960b --- /dev/null +++ b/src/include/executor/nodeGatherMerge.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + * + * nodeGatherMerge.h + * prototypes for nodeGatherMerge.c + * + * + * Portions Copyright (c) 1996-2020, 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..2965c74 --- /dev/null +++ b/src/include/executor/nodeGroup.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeGroup.h + * prototypes for nodeGroup.c + * + * + * Portions Copyright (c) 1996-2020, 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..2db4e2f --- /dev/null +++ b/src/include/executor/nodeHash.h @@ -0,0 +1,79 @@ +/*------------------------------------------------------------------------- + * + * nodeHash.h + * prototypes for nodeHash.c + * + * + * Portions Copyright (c) 1996-2020, 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..dc67162 --- /dev/null +++ b/src/include/executor/nodeHashjoin.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------- + * + * nodeHashjoin.h + * prototypes for nodeHashjoin.c + * + * + * Portions Copyright (c) 1996-2020, 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..e62c02a --- /dev/null +++ b/src/include/executor/nodeIncrementalSort.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * nodeIncrementalSort.h + * + * Portions Copyright (c) 1996-2020, 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..9f1d26f --- /dev/null +++ b/src/include/executor/nodeIndexonlyscan.h @@ -0,0 +1,36 @@ +/*------------------------------------------------------------------------- + * + * nodeIndexonlyscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..1b6b318 --- /dev/null +++ b/src/include/executor/nodeIndexscan.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------- + * + * nodeIndexscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..cbcb941 --- /dev/null +++ b/src/include/executor/nodeLimit.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeLimit.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..85d0e17 --- /dev/null +++ b/src/include/executor/nodeLockRows.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeLockRows.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..99e7cbf --- /dev/null +++ b/src/include/executor/nodeMaterial.h @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------- + * + * nodeMaterial.h + * + * + * + * Portions Copyright (c) 1996-2020, 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/nodeMergeAppend.h b/src/include/executor/nodeMergeAppend.h new file mode 100644 index 0000000..2c86189 --- /dev/null +++ b/src/include/executor/nodeMergeAppend.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeMergeAppend.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..ae8105a --- /dev/null +++ b/src/include/executor/nodeMergejoin.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeMergejoin.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..4ec4ebd --- /dev/null +++ b/src/include/executor/nodeModifyTable.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * nodeModifyTable.h + * + * + * Portions Copyright (c) 1996-2020, 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(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..6fcf08e --- /dev/null +++ b/src/include/executor/nodeNamedtuplestorescan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeNamedtuplestorescan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..5a048a7 --- /dev/null +++ b/src/include/executor/nodeNestloop.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeNestloop.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..76e433f --- /dev/null +++ b/src/include/executor/nodeProjectSet.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeProjectSet.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..c7253ce --- /dev/null +++ b/src/include/executor/nodeRecursiveunion.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeRecursiveunion.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..b861672 --- /dev/null +++ b/src/include/executor/nodeResult.h @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------- + * + * nodeResult.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..c24fca5 --- /dev/null +++ b/src/include/executor/nodeSamplescan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeSamplescan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..2ef48ce --- /dev/null +++ b/src/include/executor/nodeSeqscan.h @@ -0,0 +1,31 @@ +/*------------------------------------------------------------------------- + * + * nodeSeqscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..a3577b3 --- /dev/null +++ b/src/include/executor/nodeSetOp.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeSetOp.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..0925556 --- /dev/null +++ b/src/include/executor/nodeSort.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * nodeSort.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..83e90b3 --- /dev/null +++ b/src/include/executor/nodeSubplan.h @@ -0,0 +1,33 @@ +/*------------------------------------------------------------------------- + * + * nodeSubplan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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 AlternativeSubPlanState *ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent); + +extern Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull); + +extern Datum ExecAlternativeSubPlan(AlternativeSubPlanState *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..5e237b0 --- /dev/null +++ b/src/include/executor/nodeSubqueryscan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeSubqueryscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..644babc --- /dev/null +++ b/src/include/executor/nodeTableFuncscan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeTableFuncscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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/nodeTidscan.h b/src/include/executor/nodeTidscan.h new file mode 100644 index 0000000..92a818d --- /dev/null +++ b/src/include/executor/nodeTidscan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeTidscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..bc653fd --- /dev/null +++ b/src/include/executor/nodeUnique.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeUnique.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..5f2a1d5 --- /dev/null +++ b/src/include/executor/nodeValuesscan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeValuesscan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..4c53eb0 --- /dev/null +++ b/src/include/executor/nodeWindowAgg.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeWindowAgg.h + * prototypes for nodeWindowAgg.c + * + * + * Portions Copyright (c) 1996-2020, 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..09ecc49 --- /dev/null +++ b/src/include/executor/nodeWorktablescan.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * nodeWorktablescan.h + * + * + * + * Portions Copyright (c) 1996-2020, 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..06de20a --- /dev/null +++ b/src/include/executor/spi.h @@ -0,0 +1,175 @@ +/*------------------------------------------------------------------------- + * + * spi.h + * Server Programming Interface public declarations + * + * Portions Copyright (c) 1996-2020, 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 "nodes/parsenodes.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; + +/* 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_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, + bool read_only, long tcount); +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_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_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..5e6575d --- /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-2020, 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? */ + bool no_snapshots; /* allow nonatomic CALL/DO execution */ + List *plancache_list; /* one CachedPlanSource per parsetree */ + MemoryContext plancxt; /* Context containing _SPI_plan and data */ + 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..4131056 --- /dev/null +++ b/src/include/executor/tablefunc.h @@ -0,0 +1,67 @@ +/*------------------------------------------------------------------------- + * + * tablefunc.h + * interface for TableFunc executor node + * + * Portions Copyright (c) 1996-2020, 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..93655ef --- /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-2020, 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 HeapTuple 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..b2390c4 --- /dev/null +++ b/src/include/executor/tstoreReceiver.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * + * tstoreReceiver.h + * prototypes for tstoreReceiver.c + * + * + * Portions Copyright (c) 1996-2020, 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); + +#endif /* TSTORE_RECEIVER_H */ diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h new file mode 100644 index 0000000..f7df70b --- /dev/null +++ b/src/include/executor/tuptable.h @@ -0,0 +1,487 @@ +/*------------------------------------------------------------------------- + * + * tuptable.h + * tuple table support stuff + * + * + * Portions Copyright (c) 1996-2020, 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 */ |