* definitions for executor state nodes
*
*
- * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: execnodes.h,v 1.105 2003/08/22 20:26:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.199 2009/01/01 17:23:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef EXECNODES_H
#define EXECNODES_H
-#include "access/relscan.h"
-#include "executor/hashjoin.h"
-#include "executor/tuptable.h"
-#include "fmgr.h"
-#include "nodes/bitmapset.h"
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/skey.h"
#include "nodes/params.h"
-#include "nodes/plannodes.h"
+#include "nodes/plannodes.h"
+#include "nodes/tidbitmap.h"
#include "utils/hsearch.h"
+#include "utils/rel.h"
+#include "utils/snapshot.h"
#include "utils/tuplestore.h"
* Predicate partial-index predicate, or NIL if none
* PredicateState exec state for predicate, or NIL if none
* Unique is it a unique index?
+ * ReadyForInserts is it valid for inserts?
+ * Concurrent are we doing a concurrent index build?
+ * BrokenHotChain did we detect any broken HOT chains?
+ *
+ * ii_Concurrent and ii_BrokenHotChain are used only during index build;
+ * they're conventionally set to false otherwise.
* ----------------
*/
typedef struct IndexInfo
List *ii_Predicate; /* list of Expr */
List *ii_PredicateState; /* list of ExprState */
bool ii_Unique;
+ bool ii_ReadyForInserts;
+ bool ii_Concurrent;
+ bool ii_BrokenHotChain;
} IndexInfo;
/* ----------------
ParamExecData *ecxt_param_exec_vals; /* for PARAM_EXEC params */
ParamListInfo ecxt_param_list_info; /* for other param types */
- /* Values to substitute for Aggref nodes in expression */
- Datum *ecxt_aggvalues; /* precomputed values for Aggref nodes */
- bool *ecxt_aggnulls; /* null flags for Aggref nodes */
+ /*
+ * Values to substitute for Aggref nodes in the expressions of an Agg node,
+ * or for WindowFunc nodes within a WindowAgg node.
+ */
+ Datum *ecxt_aggvalues; /* precomputed values for aggs/windowfuncs */
+ bool *ecxt_aggnulls; /* null flags for aggs/windowfuncs */
+
+ /* Value to substitute for CaseTestExpr nodes in expression */
+ Datum caseValue_datum;
+ bool caseValue_isNull;
/* Value to substitute for CoerceToDomainValue nodes in expression */
Datum domainValue_datum;
bool domainValue_isNull;
- /* Link to containing EState */
+ /* Link to containing EState (NULL if a standalone ExprContext) */
struct EState *ecxt_estate;
/* Functions to call back when ExprContext is shut down */
/*
* Return modes for functions returning sets. Note values must be chosen
* as separate bits so that a bitmask can be formed to indicate supported
- * modes.
+ * modes. SFRM_Materialize_Random and SFRM_Materialize_Preferred are
+ * auxiliary flags about SFRM_Materialize mode, rather than separate modes.
*/
typedef enum
{
SFRM_ValuePerCall = 0x01, /* one value returned per call */
- SFRM_Materialize = 0x02 /* result set instantiated in Tuplestore */
+ SFRM_Materialize = 0x02, /* result set instantiated in Tuplestore */
+ SFRM_Materialize_Random = 0x04, /* Tuplestore needs randomAccess */
+ SFRM_Materialize_Preferred = 0x08 /* caller prefers Tuplestore */
} SetFunctionReturnMode;
/*
* This is all the information needed to perform projections ---
* that is, form new tuples by evaluation of targetlist expressions.
* Nodes which need to do projections create one of these.
- * In theory, when a node wants to perform a projection
- * it should just update this information as necessary and then
- * call ExecProject(). -cim 6/3/91
*
* ExecProject() evaluates the tlist, forms a tuple, and stores it
- * in the given slot. As a side-effect, the actual datum values and
- * null indicators are placed in the work arrays tupValues/tupNulls.
+ * in the given slot. Note that the result will be a "virtual" tuple
+ * unless ExecMaterializeSlot() is then called to force it to be
+ * converted to a physical tuple. The slot must have a tupledesc
+ * that matches the output of the tlist!
+ *
+ * The planner very often produces tlists that consist entirely of
+ * simple Var references (lower levels of a plan tree almost always
+ * look like that). So we have an optimization to handle that case
+ * with minimum overhead.
*
* targetlist target list for projection
* exprContext expression context in which to evaluate targetlist
* slot slot to place projection result in
- * tupValues array of computed values
- * tupNull array of null indicators
* itemIsDone workspace for ExecProject
+ * isVarList TRUE if simple-Var-list optimization applies
+ * varSlotOffsets array indicating which slot each simple Var is from
+ * varNumbers array indicating attr numbers of simple Vars
+ * lastInnerVar highest attnum from inner tuple slot (0 if none)
+ * lastOuterVar highest attnum from outer tuple slot (0 if none)
+ * lastScanVar highest attnum from scan tuple slot (0 if none)
* ----------------
*/
typedef struct ProjectionInfo
List *pi_targetlist;
ExprContext *pi_exprContext;
TupleTableSlot *pi_slot;
- Datum *pi_tupValues;
- char *pi_tupNulls;
ExprDoneCond *pi_itemIsDone;
+ bool pi_isVarList;
+ int *pi_varSlotOffsets;
+ int *pi_varNumbers;
+ int pi_lastInnerVar;
+ int pi_lastOuterVar;
+ int pi_lastScanVar;
} ProjectionInfo;
/* ----------------
* This class is used to store information regarding junk attributes.
* A junk attribute is an attribute in a tuple that is needed only for
* storing intermediate information in the executor, and does not belong
- * in emitted tuples. For example, when we do an UPDATE query,
+ * in emitted tuples. For example, when we do an UPDATE query,
* the planner adds a "junk" entry to the targetlist so that the tuples
* returned to ExecutePlan() contain an extra attribute: the ctid of
* the tuple to be updated. This is needed to do the update, but we
* don't want the ctid to be part of the stored new tuple! So, we
* apply a "junk filter" to remove the junk attributes and form the
- * real output tuple.
+ * real output tuple. The junkfilter code also provides routines to
+ * extract the values of the junk attribute(s) from the input tuple.
*
* targetList: the original target list (including junk attributes).
- * length: the length of 'targetList'.
- * tupType: the tuple descriptor for the "original" tuple
- * (including the junk attributes).
- * cleanTargetList: the "clean" target list (junk attributes removed).
- * cleanLength: the length of 'cleanTargetList'
- * cleanTupType: the tuple descriptor of the "clean" tuple (with
+ * cleanTupType: the tuple descriptor for the "clean" tuple (with
* junk attributes removed).
* cleanMap: A map with the correspondence between the non-junk
* attribute numbers of the "original" tuple and the
* attribute numbers of the "clean" tuple.
- * resultSlot: tuple slot that can be used to hold cleaned tuple.
+ * resultSlot: tuple slot used to hold cleaned tuple.
+ * junkAttNo: not used by junkfilter code. Can be used by caller
+ * to remember the attno of a specific junk attribute
+ * (execMain.c stores the "ctid" attno here).
* ----------------
*/
typedef struct JunkFilter
{
NodeTag type;
List *jf_targetList;
- int jf_length;
- TupleDesc jf_tupType;
- List *jf_cleanTargetList;
- int jf_cleanLength;
TupleDesc jf_cleanTupType;
AttrNumber *jf_cleanMap;
TupleTableSlot *jf_resultSlot;
+ AttrNumber jf_junkAttNo;
} JunkFilter;
/* ----------------
* IndexRelationInfo array of key/attr info for indices
* TrigDesc triggers to be fired, if any
* TrigFunctions cached lookup info for trigger functions
+ * TrigInstrument optional runtime measurements for triggers
* ConstraintExprs array of constraint-checking expr states
* junkFilter for removing junk attributes from tuples
+ * projectReturning for computing a RETURNING list
* ----------------
*/
typedef struct ResultRelInfo
IndexInfo **ri_IndexRelationInfo;
TriggerDesc *ri_TrigDesc;
FmgrInfo *ri_TrigFunctions;
+ struct Instrumentation *ri_TrigInstrument;
List **ri_ConstraintExprs;
JunkFilter *ri_junkFilter;
+ ProjectionInfo *ri_projectReturning;
} ResultRelInfo;
/* ----------------
/* Basic state for all query types: */
ScanDirection es_direction; /* current scan direction */
Snapshot es_snapshot; /* time qual to use */
- List *es_range_table; /* List of RangeTableEntrys */
+ Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
+ List *es_range_table; /* List of RangeTblEntry */
+
+ /* If query can insert/delete tuples, the command ID to mark them with */
+ CommandId es_output_cid;
/* Info about target table for insert/update/delete queries: */
ResultRelInfo *es_result_relations; /* array of ResultRelInfos */
int es_num_result_relations; /* length of array */
- ResultRelInfo *es_result_relation_info; /* currently active array
- * elt */
+ ResultRelInfo *es_result_relation_info; /* currently active array elt */
JunkFilter *es_junkFilter; /* currently active junk filter */
- Relation es_into_relation_descriptor; /* for SELECT INTO */
+
+ /* Stuff used for firing triggers: */
+ List *es_trig_target_relations; /* trigger-only ResultRelInfos */
+ TupleTableSlot *es_trig_tuple_slot; /* for trigger output tuples */
/* Parameter info: */
ParamListInfo es_param_list_info; /* values of external params */
uint32 es_processed; /* # of tuples processed */
Oid es_lastoid; /* last oid processed (by INSERT) */
- List *es_rowMark; /* not good place, but there is no other */
+ List *es_rowMarks; /* not good place, but there is no other */
bool es_instrument; /* true requests runtime instrumentation */
- bool es_force_oids; /* true forces result tuples to have
- * (space for) OIDs --- used for SELECT
- * INTO */
+ bool es_select_into; /* true if doing SELECT INTO */
+ bool es_into_oids; /* true to generate OIDs in SELECT INTO */
List *es_exprcontexts; /* List of ExprContexts within EState */
+ List *es_subplanstates; /* List of PlanState for SubPlans */
+
/*
- * this ExprContext is for per-output-tuple operations, such as
- * constraint checks and index-value computations. It will be reset
- * for each output tuple. Note that it will be created only if
- * needed.
+ * this ExprContext is for per-output-tuple operations, such as constraint
+ * checks and index-value computations. It will be reset for each output
+ * tuple. Note that it will be created only if needed.
*/
ExprContext *es_per_tuple_exprcontext;
/* Below is to re-evaluate plan qual in READ COMMITTED mode */
- Plan *es_topPlan; /* link to top of plan tree */
- struct evalPlanQual *es_evalPlanQual; /* chain of PlanQual
- * states */
+ PlannedStmt *es_plannedstmt; /* link to top of plan tree */
+ struct evalPlanQual *es_evalPlanQual; /* chain of PlanQual states */
bool *es_evTupleNull; /* local array of EPQ status */
HeapTuple *es_evTuple; /* shared array of EPQ substitute tuples */
bool es_useEvalPlan; /* evaluating EPQ tuples? */
} EState;
+/*
+ * es_rowMarks is a list of these structs. See RowMarkClause for details
+ * about rti and prti. toidAttno is not used in a "plain" rowmark.
+ */
+typedef struct ExecRowMark
+{
+ Relation relation; /* opened and RowShareLock'd relation */
+ Index rti; /* its range table index */
+ Index prti; /* parent range table index, if child */
+ bool forUpdate; /* true = FOR UPDATE, false = FOR SHARE */
+ bool noWait; /* NOWAIT option */
+ AttrNumber ctidAttNo; /* resno of its ctid junk attribute */
+ AttrNumber toidAttNo; /* resno of tableoid junk attribute, if any */
+ ItemPointerData curCtid; /* ctid of currently locked tuple, if any */
+} ExecRowMark;
+
+
/* ----------------------------------------------------------------
* Tuple Hash Tables
*
* All-in-memory tuple hash tables are used for a number of purposes.
+ *
+ * Note: tab_hash_funcs are for the key datatype(s) stored in the table,
+ * and tab_eq_funcs are non-cross-type equality operators for those types.
+ * Normally these are the only functions used, but FindTupleHashEntry()
+ * supports searching a hashtable using cross-data-type hashing. For that,
+ * the caller must supply hash functions for the LHS datatype as well as
+ * the cross-type equality operators to use. in_hash_funcs and cur_eq_funcs
+ * are set to point to the caller's function arrays while doing such a search.
+ * During LookupTupleHashEntry(), they point to tab_hash_funcs and
+ * tab_eq_funcs respectively.
* ----------------------------------------------------------------
*/
typedef struct TupleHashEntryData *TupleHashEntry;
typedef struct TupleHashEntryData
{
/* firstTuple must be the first field in this struct! */
- HeapTuple firstTuple; /* copy of first tuple in this group */
+ MinimalTuple firstTuple; /* copy of first tuple in this group */
/* there may be additional data beyond the end of this struct */
} TupleHashEntryData; /* VARIABLE LENGTH STRUCT */
HTAB *hashtab; /* underlying dynahash table */
int numCols; /* number of columns in lookup key */
AttrNumber *keyColIdx; /* attr numbers of key columns */
- FmgrInfo *eqfunctions; /* lookup data for comparison functions */
- FmgrInfo *hashfunctions; /* lookup data for hash functions */
+ FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */
+ FmgrInfo *tab_eq_funcs; /* equality functions for table datatype(s) */
MemoryContext tablecxt; /* memory context containing table */
MemoryContext tempcxt; /* context for function evaluations */
Size entrysize; /* actual size to make each hash entry */
- TupleDesc tupdesc; /* tuple descriptor */
+ TupleTableSlot *tableslot; /* slot for referencing table entries */
+ /* The following fields are set transiently for each table search: */
+ TupleTableSlot *inputslot; /* current input tuple's slot */
+ FmgrInfo *in_hash_funcs; /* hash functions for input datatype(s) */
+ FmgrInfo *cur_eq_funcs; /* equality functions for input vs. table */
} TupleHashTableData;
typedef HASH_SEQ_STATUS TupleHashIterator;
-#define ResetTupleHashIterator(htable, iter) \
+/*
+ * Use InitTupleHashIterator/TermTupleHashIterator for a read/write scan.
+ * Use ResetTupleHashIterator if the table can be frozen (in this case no
+ * explicit scan termination is needed).
+ */
+#define InitTupleHashIterator(htable, iter) \
hash_seq_init(iter, (htable)->hashtab)
+#define TermTupleHashIterator(iter) \
+ hash_seq_term(iter)
+#define ResetTupleHashIterator(htable, iter) \
+ do { \
+ hash_freeze((htable)->hashtab); \
+ hash_seq_init(iter, (htable)->hashtab); \
+ } while (0)
#define ScanTupleHashTable(iter) \
((TupleHashEntry) hash_seq_search(iter))
*
* It can also be instantiated directly for leaf Expr nodes that need no
* local run-time state (such as Var, Const, or Param).
+ *
+ * To save on dispatch overhead, each ExprState node contains a function
+ * pointer to the routine to execute to evaluate the node.
* ----------------
*/
-typedef struct ExprState
+
+typedef struct ExprState ExprState;
+
+typedef Datum (*ExprStateEvalFunc) (ExprState *expression,
+ ExprContext *econtext,
+ bool *isNull,
+ ExprDoneCond *isDone);
+
+struct ExprState
{
NodeTag type;
Expr *expr; /* associated Expr node */
-} ExprState;
+ ExprStateEvalFunc evalfunc; /* routine to run to execute node */
+};
/* ----------------
* GenericExprState node
typedef struct AggrefExprState
{
ExprState xprstate;
- ExprState *target; /* state of my child node */
+ List *args; /* states of argument expressions */
int aggno; /* ID number for agg within its plan node */
} AggrefExprState;
+/* ----------------
+ * WindowFuncExprState node
+ * ----------------
+ */
+typedef struct WindowFuncExprState
+{
+ ExprState xprstate;
+ List *args; /* states of argument expressions */
+ int wfuncno; /* ID number for wfunc within its plan node */
+} WindowFuncExprState;
+
/* ----------------
* ArrayRefExprState node
*
List *args; /* states of argument expressions */
/*
- * Function manager's lookup info for the target function. If
- * func.fn_oid is InvalidOid, we haven't initialized it yet.
+ * Function manager's lookup info for the target function. If func.fn_oid
+ * is InvalidOid, we haven't initialized it yet (nor any of the following
+ * fields).
*/
FmgrInfo func;
/*
- * We also need to store argument values across calls when evaluating
- * a function-returning-set.
+ * For a set-returning function (SRF) that returns a tuplestore, we
+ * keep the tuplestore here and dole out the result rows one at a time.
+ * The slot holds the row currently being returned.
+ */
+ Tuplestorestate *funcResultStore;
+ TupleTableSlot *funcResultSlot;
+
+ /*
+ * In some cases we need to compute a tuple descriptor for the function's
+ * output. If so, it's stored here.
+ */
+ TupleDesc funcResultDesc;
+ bool funcReturnsTuple; /* valid when funcResultDesc isn't NULL */
+
+ /*
+ * We need to store argument values across calls when evaluating a SRF
+ * that uses value-per-call mode.
*
* setArgsValid is true when we are evaluating a set-valued function and
* we are in the middle of a call series; we want to pass the same
/*
* Flag to remember whether we found a set-valued argument to the
- * function. This causes the function result to be a set as well.
- * Valid only when setArgsValid is true.
+ * function. This causes the function result to be a set as well. Valid
+ * only when setArgsValid is true or funcResultStore isn't NULL.
*/
bool setHasSetArg; /* some argument returns a set */
/*
- * Current argument data for a set-valued function; contains valid
- * data only if setArgsValid is true.
+ * Flag to remember whether we have registered a shutdown callback for
+ * this FuncExprState. We do so only if funcResultStore or setArgsValid
+ * has been set at least once (since all the callback is for is to release
+ * the tuplestore or clear setArgsValid).
+ */
+ bool shutdown_reg; /* a shutdown callback is registered */
+
+ /*
+ * Current argument data for a set-valued function; contains valid data
+ * only if setArgsValid is true.
*/
FunctionCallInfoData setArgs;
} FuncExprState;
typedef struct SubPlanState
{
ExprState xprstate;
- EState *sub_estate; /* subselect plan has its own EState */
struct PlanState *planstate; /* subselect plan's state tree */
- List *exprs; /* states of combining expression(s) */
+ ExprState *testexpr; /* state of combining expression */
List *args; /* states of argument expression(s) */
- bool needShutdown; /* TRUE = need to shutdown subplan */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
/* these are used when hashing the subselect's output: */
ProjectionInfo *projLeft; /* for projecting lefthand exprs */
MemoryContext tablecxt; /* memory context containing tables */
ExprContext *innerecontext; /* working context for comparisons */
AttrNumber *keyColIdx; /* control data for hash tables */
- FmgrInfo *eqfunctions; /* comparison functions for hash tables */
- FmgrInfo *hashfunctions; /* lookup data for hash functions */
+ FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */
+ FmgrInfo *tab_eq_funcs; /* equality functions for table datatype(s) */
+ FmgrInfo *lhs_hash_funcs; /* hash functions for lefthand datatype(s) */
+ FmgrInfo *cur_eq_funcs; /* equality functions for LHS vs. table */
} SubPlanState;
+/* ----------------
+ * AlternativeSubPlanState node
+ * ----------------
+ */
+typedef struct AlternativeSubPlanState
+{
+ ExprState xprstate;
+ List *subplans; /* states of alternative subplans */
+ int active; /* list index of the one we're using */
+} AlternativeSubPlanState;
+
+/* ----------------
+ * FieldSelectState node
+ * ----------------
+ */
+typedef struct FieldSelectState
+{
+ ExprState xprstate;
+ ExprState *arg; /* input expression */
+ TupleDesc argdesc; /* tupdesc for most recent input */
+} FieldSelectState;
+
+/* ----------------
+ * FieldStoreState node
+ * ----------------
+ */
+typedef struct FieldStoreState
+{
+ ExprState xprstate;
+ ExprState *arg; /* input tuple value */
+ List *newvals; /* new value(s) for field(s) */
+ TupleDesc argdesc; /* tupdesc for most recent input */
+} FieldStoreState;
+
+/* ----------------
+ * CoerceViaIOState node
+ * ----------------
+ */
+typedef struct CoerceViaIOState
+{
+ ExprState xprstate;
+ ExprState *arg; /* input expression */
+ FmgrInfo outfunc; /* lookup info for source output function */
+ FmgrInfo infunc; /* lookup info for result input function */
+ Oid intypioparam; /* argument needed for input function */
+} CoerceViaIOState;
+
+/* ----------------
+ * ArrayCoerceExprState node
+ * ----------------
+ */
+typedef struct ArrayCoerceExprState
+{
+ ExprState xprstate;
+ ExprState *arg; /* input array value */
+ Oid resultelemtype; /* element type of result array */
+ FmgrInfo elemfunc; /* lookup info for element coercion function */
+ /* use struct pointer to avoid including array.h here */
+ struct ArrayMapState *amstate; /* workspace for array_map */
+} ArrayCoerceExprState;
+
+/* ----------------
+ * ConvertRowtypeExprState node
+ * ----------------
+ */
+typedef struct ConvertRowtypeExprState
+{
+ ExprState xprstate;
+ ExprState *arg; /* input tuple value */
+ TupleDesc indesc; /* tupdesc for source rowtype */
+ TupleDesc outdesc; /* tupdesc for result rowtype */
+ AttrNumber *attrMap; /* indexes of input fields, or 0 for null */
+ Datum *invalues; /* workspace for deconstructing source */
+ bool *inisnull;
+ Datum *outvalues; /* workspace for constructing result */
+ bool *outisnull;
+} ConvertRowtypeExprState;
+
/* ----------------
* CaseExprState node
* ----------------
typedef struct CaseExprState
{
ExprState xprstate;
+ ExprState *arg; /* implicit equality comparison argument */
List *args; /* the arguments (list of WHEN clauses) */
ExprState *defresult; /* the default result (ELSE clause) */
} CaseExprState;
char elemalign; /* typalign of the element type */
} ArrayExprState;
+/* ----------------
+ * RowExprState node
+ * ----------------
+ */
+typedef struct RowExprState
+{
+ ExprState xprstate;
+ List *args; /* the arguments */
+ TupleDesc tupdesc; /* descriptor for result tuples */
+} RowExprState;
+
+/* ----------------
+ * RowCompareExprState node
+ * ----------------
+ */
+typedef struct RowCompareExprState
+{
+ ExprState xprstate;
+ List *largs; /* the left-hand input arguments */
+ List *rargs; /* the right-hand input arguments */
+ FmgrInfo *funcs; /* array of comparison function info */
+} RowCompareExprState;
+
/* ----------------
* CoalesceExprState node
* ----------------
List *args; /* the arguments */
} CoalesceExprState;
+/* ----------------
+ * MinMaxExprState node
+ * ----------------
+ */
+typedef struct MinMaxExprState
+{
+ ExprState xprstate;
+ List *args; /* the arguments */
+ FmgrInfo cfunc; /* lookup info for comparison func */
+} MinMaxExprState;
+
+/* ----------------
+ * XmlExprState node
+ * ----------------
+ */
+typedef struct XmlExprState
+{
+ ExprState xprstate;
+ List *named_args; /* ExprStates for named arguments */
+ FmgrInfo *named_outfuncs; /* array of output fns for named arguments */
+ List *args; /* ExprStates for other arguments */
+} XmlExprState;
+
+/* ----------------
+ * NullTestState node
+ * ----------------
+ */
+typedef struct NullTestState
+{
+ ExprState xprstate;
+ ExprState *arg; /* input expression */
+ bool argisrow; /* T if input is of a composite type */
+ /* used only if argisrow: */
+ TupleDesc argdesc; /* tupdesc for most recent input */
+} NullTestState;
+
/* ----------------
* CoerceToDomainState node
* ----------------
Plan *plan; /* associated Plan node */
- EState *state; /* at execution time, state's of
- * individual nodes point to one EState
- * for the whole top-level plan */
+ EState *state; /* at execution time, states of individual
+ * nodes point to one EState for the whole
+ * top-level plan */
struct Instrumentation *instrument; /* Optional runtime stats for this
* plan node */
/*
- * Common structural data for all Plan types. These links to
- * subsidiary state trees parallel links in the associated plan tree
- * (except for the subPlan list, which does not exist in the plan
- * tree).
+ * Common structural data for all Plan types. These links to subsidiary
+ * state trees parallel links in the associated plan tree (except for the
+ * subPlan list, which does not exist in the plan tree).
*/
List *targetlist; /* target list to be computed at this node */
List *qual; /* implicitly-ANDed qual conditions */
struct PlanState *lefttree; /* input plan tree(s) */
struct PlanState *righttree;
- List *initPlan; /* Init SubPlanState nodes (un-correlated
- * expr subselects) */
+ List *initPlan; /* Init SubPlanState nodes (un-correlated expr
+ * subselects) */
List *subPlan; /* SubPlanState nodes in my expressions */
/*
/*
* Other run-time state needed by most if not all node types.
*/
- TupleTableSlot *ps_OuterTupleSlot; /* slot for current "outer" tuple */
TupleTableSlot *ps_ResultTupleSlot; /* slot for my result tuples */
ExprContext *ps_ExprContext; /* node's expression-evaluation context */
ProjectionInfo *ps_ProjInfo; /* info for doing tuple projection */
- bool ps_TupFromTlist;/* state flag for processing set-valued
- * functions in targetlist */
+ bool ps_TupFromTlist; /* state flag for processing set-valued
+ * functions in targetlist */
} PlanState;
/* ----------------
int as_lastplan;
} AppendState;
+/* ----------------
+ * RecursiveUnionState information
+ *
+ * RecursiveUnionState is used for performing a recursive union.
+ *
+ * recursing T when we're done scanning the non-recursive term
+ * intermediate_empty T if intermediate_table is currently empty
+ * working_table working table (to be scanned by recursive term)
+ * intermediate_table current recursive output (next generation of WT)
+ * ----------------
+ */
+typedef struct RecursiveUnionState
+{
+ PlanState ps; /* its first field is NodeTag */
+ bool recursing;
+ bool intermediate_empty;
+ Tuplestorestate *working_table;
+ Tuplestorestate *intermediate_table;
+ /* Remaining fields are unused in UNION ALL case */
+ FmgrInfo *eqfunctions; /* per-grouping-field equality fns */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ MemoryContext tempContext; /* short-term context for comparisons */
+ TupleHashTable hashtable; /* hash table for tuples already seen */
+ MemoryContext tableContext; /* memory context containing hash table */
+} RecursiveUnionState;
+
+/* ----------------
+ * BitmapAndState information
+ * ----------------
+ */
+typedef struct BitmapAndState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **bitmapplans; /* array of PlanStates for my inputs */
+ int nplans; /* number of input plans */
+} BitmapAndState;
+
+/* ----------------
+ * BitmapOrState information
+ * ----------------
+ */
+typedef struct BitmapOrState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **bitmapplans; /* array of PlanStates for my inputs */
+ int nplans; /* number of input plans */
+} BitmapOrState;
+
/* ----------------------------------------------------------------
* Scan State Information
* ----------------------------------------------------------------
*/
typedef ScanState SeqScanState;
+/*
+ * These structs store information about index quals that don't have simple
+ * constant right-hand sides. See comments for ExecIndexBuildScanKeys()
+ * for discussion.
+ */
+typedef struct
+{
+ ScanKey scan_key; /* scankey to put value into */
+ ExprState *key_expr; /* expr to evaluate to get value */
+} IndexRuntimeKeyInfo;
+
+typedef struct
+{
+ ScanKey scan_key; /* scankey to put value into */
+ ExprState *array_expr; /* expr to evaluate to get array value */
+ int next_elem; /* next array element to use */
+ int num_elems; /* number of elems in current array value */
+ Datum *elem_values; /* array of num_elems Datums */
+ bool *elem_nulls; /* array of num_elems is-null flags */
+} IndexArrayKeyInfo;
+
/* ----------------
* IndexScanState information
*
- * NumIndices number of indices in this scan
- * IndexPtr current index in use
- * ScanKeys Skey structures to scan index rels
- * NumScanKeys array of no of keys in each Skey struct
- * RuntimeKeyInfo array of array of exprstates for Skeys
- * that will be evaluated at runtime
- * RuntimeContext expr context for evaling runtime Skeys
+ * indexqualorig execution state for indexqualorig expressions
+ * ScanKeys Skey structures to scan index rel
+ * NumScanKeys number of Skey structs
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys structs
* RuntimeKeysReady true if runtime Skeys have been computed
- * RelationDescs ptr to array of relation descriptors
- * ScanDescs ptr to array of scan descriptors
- * DupHash hashtable for recognizing dups in multiple scan
- * MaxHash max # entries we will allow in hashtable
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
* ----------------
*/
typedef struct IndexScanState
{
ScanState ss; /* its first field is NodeTag */
- List *indxqual;
- List *indxqualorig;
- int iss_NumIndices;
- int iss_IndexPtr;
- int iss_MarkIndexPtr;
- ScanKey *iss_ScanKeys;
- int *iss_NumScanKeys;
- ExprState ***iss_RuntimeKeyInfo;
- ExprContext *iss_RuntimeContext;
+ List *indexqualorig;
+ ScanKey iss_ScanKeys;
+ int iss_NumScanKeys;
+ IndexRuntimeKeyInfo *iss_RuntimeKeys;
+ int iss_NumRuntimeKeys;
bool iss_RuntimeKeysReady;
- RelationPtr iss_RelationDescs;
- IndexScanDescPtr iss_ScanDescs;
- HTAB *iss_DupHash;
- long iss_MaxHash;
+ ExprContext *iss_RuntimeContext;
+ Relation iss_RelationDesc;
+ IndexScanDesc iss_ScanDesc;
} IndexScanState;
+/* ----------------
+ * BitmapIndexScanState information
+ *
+ * result bitmap to return output into, or NULL
+ * ScanKeys Skey structures to scan index rel
+ * NumScanKeys number of Skey structs
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys structs
+ * ArrayKeys info about Skeys that come from ScalarArrayOpExprs
+ * NumArrayKeys number of ArrayKeys structs
+ * RuntimeKeysReady true if runtime Skeys have been computed
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
+ * ----------------
+ */
+typedef struct BitmapIndexScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ TIDBitmap *biss_result;
+ ScanKey biss_ScanKeys;
+ int biss_NumScanKeys;
+ IndexRuntimeKeyInfo *biss_RuntimeKeys;
+ int biss_NumRuntimeKeys;
+ IndexArrayKeyInfo *biss_ArrayKeys;
+ int biss_NumArrayKeys;
+ bool biss_RuntimeKeysReady;
+ ExprContext *biss_RuntimeContext;
+ Relation biss_RelationDesc;
+ IndexScanDesc biss_ScanDesc;
+} BitmapIndexScanState;
+
+/* ----------------
+ * BitmapHeapScanState information
+ *
+ * bitmapqualorig execution state for bitmapqualorig expressions
+ * tbm bitmap obtained from child index scan(s)
+ * tbmres current-page data
+ * ----------------
+ */
+typedef struct BitmapHeapScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ List *bitmapqualorig;
+ TIDBitmap *tbm;
+ TBMIterateResult *tbmres;
+} BitmapHeapScanState;
+
/* ----------------
* TidScanState information
*
+ * isCurrentOf scan has a CurrentOfExpr qual
* NumTids number of tids in this scan
- * TidPtr current tid in use
- * TidList evaluated item pointers
+ * TidPtr index of currently fetched tid
+ * TidList evaluated item pointers (array of size NumTids)
* ----------------
*/
typedef struct TidScanState
{
ScanState ss; /* its first field is NodeTag */
- List *tss_tideval; /* list of ExprState nodes */
+ List *tss_tidquals; /* list of ExprState nodes */
+ bool tss_isCurrentOf;
int tss_NumTids;
int tss_TidPtr;
int tss_MarkTidPtr;
* SubqueryScanState information
*
* SubqueryScanState is used for scanning a sub-query in the range table.
- * The sub-query will have its own EState, which we save here.
* ScanTupleSlot references the current output tuple of the sub-query.
- *
- * SubEState exec state for sub-query
* ----------------
*/
typedef struct SubqueryScanState
{
ScanState ss; /* its first field is NodeTag */
PlanState *subplan;
- EState *sss_SubEState;
} SubqueryScanState;
/* ----------------
* Function nodes are used to scan the results of a
* function appearing in FROM (typically a function returning set).
*
+ * eflags node's capability flags
* tupdesc expected return tuple description
* tuplestorestate private state of tuplestore.c
* funcexpr state for function expression being evaluated
typedef struct FunctionScanState
{
ScanState ss; /* its first field is NodeTag */
+ int eflags;
TupleDesc tupdesc;
Tuplestorestate *tuplestorestate;
ExprState *funcexpr;
} FunctionScanState;
+/* ----------------
+ * ValuesScanState information
+ *
+ * ValuesScan nodes are used to scan the results of a VALUES list
+ *
+ * rowcontext per-expression-list context
+ * exprlists array of expression lists being evaluated
+ * array_len size of array
+ * curr_idx current array index (0-based)
+ * marked_idx marked position (for mark/restore)
+ *
+ * Note: ss.ps.ps_ExprContext is used to evaluate any qual or projection
+ * expressions attached to the node. We create a second ExprContext,
+ * rowcontext, in which to build the executor expression state for each
+ * Values sublist. Resetting this context lets us get rid of expression
+ * state for each row, avoiding major memory leakage over a long values list.
+ * ----------------
+ */
+typedef struct ValuesScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprContext *rowcontext;
+ List **exprlists;
+ int array_len;
+ int curr_idx;
+ int marked_idx;
+} ValuesScanState;
+
+/* ----------------
+ * CteScanState information
+ *
+ * CteScan nodes are used to scan a CommonTableExpr query.
+ *
+ * Multiple CteScan nodes can read out from the same CTE query. We use
+ * a tuplestore to hold rows that have been read from the CTE query but
+ * not yet consumed by all readers.
+ * ----------------
+ */
+typedef struct CteScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int eflags; /* capability flags to pass to tuplestore */
+ int readptr; /* index of my tuplestore read pointer */
+ PlanState *cteplanstate; /* PlanState for the CTE query itself */
+ /* Link to the "leader" CteScanState (possibly this same node) */
+ struct CteScanState *leader;
+ /* The remaining fields are only valid in the "leader" CteScanState */
+ Tuplestorestate *cte_table; /* rows already read from the CTE query */
+ bool eof_cte; /* reached end of CTE query? */
+} CteScanState;
+
+/* ----------------
+ * WorkTableScanState information
+ *
+ * WorkTableScan nodes are used to scan the work table created by
+ * a RecursiveUnion node. We locate the RecursiveUnion node
+ * during executor startup.
+ * ----------------
+ */
+typedef struct WorkTableScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ RecursiveUnionState *rustate;
+} WorkTableScanState;
+
/* ----------------------------------------------------------------
* Join State Information
* ----------------------------------------------------------------
/* ----------------
* MergeJoinState information
*
- * OuterSkipQual outerKey1 < innerKey1 ...
- * InnerSkipQual outerKey1 > innerKey1 ...
- * JoinState current "state" of join. see executor.h
+ * NumClauses number of mergejoinable join clauses
+ * Clauses info for each mergejoinable clause
+ * JoinState current "state" of join. see execdefs.h
+ * ExtraMarks true to issue extra Mark operations on inner scan
+ * FillOuter true if should emit unjoined outer tuples anyway
+ * FillInner true if should emit unjoined inner tuples anyway
* MatchedOuter true if found a join match for current outer tuple
* MatchedInner true if found a join match for current inner tuple
- * OuterTupleSlot pointer to slot in tuple table for cur outer tuple
- * InnerTupleSlot pointer to slot in tuple table for cur inner tuple
- * MarkedTupleSlot pointer to slot in tuple table for marked tuple
+ * OuterTupleSlot slot in tuple table for cur outer tuple
+ * InnerTupleSlot slot in tuple table for cur inner tuple
+ * MarkedTupleSlot slot in tuple table for marked tuple
* NullOuterTupleSlot prepared null tuple for right outer joins
* NullInnerTupleSlot prepared null tuple for left outer joins
+ * OuterEContext workspace for computing outer tuple's join values
+ * InnerEContext workspace for computing inner tuple's join values
* ----------------
*/
+/* private in nodeMergejoin.c: */
+typedef struct MergeJoinClauseData *MergeJoinClause;
+
typedef struct MergeJoinState
{
JoinState js; /* its first field is NodeTag */
- List *mergeclauses; /* list of ExprState nodes */
- List *mj_OuterSkipQual; /* list of ExprState nodes */
- List *mj_InnerSkipQual; /* list of ExprState nodes */
+ int mj_NumClauses;
+ MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */
int mj_JoinState;
+ bool mj_ExtraMarks;
+ bool mj_FillOuter;
+ bool mj_FillInner;
bool mj_MatchedOuter;
bool mj_MatchedInner;
TupleTableSlot *mj_OuterTupleSlot;
TupleTableSlot *mj_MarkedTupleSlot;
TupleTableSlot *mj_NullOuterTupleSlot;
TupleTableSlot *mj_NullInnerTupleSlot;
+ ExprContext *mj_OuterEContext;
+ ExprContext *mj_InnerEContext;
} MergeJoinState;
/* ----------------
* HashJoinState information
*
* hj_HashTable hash table for the hashjoin
+ * (NULL if table not built yet)
+ * hj_CurHashValue hash value for current outer tuple
* hj_CurBucketNo bucket# for current outer tuple
* hj_CurTuple last inner tuple matched to current outer
* tuple, or NULL if starting search
- * (CurBucketNo and CurTuple are meaningless
- * unless OuterTupleSlot is nonempty!)
+ * (CurHashValue, CurBucketNo and CurTuple are
+ * undefined if OuterTupleSlot is empty!)
* hj_OuterHashKeys the outer hash keys in the hashjoin condition
* hj_InnerHashKeys the inner hash keys in the hashjoin condition
* hj_HashOperators the join operators in the hashjoin condition
* hj_OuterTupleSlot tuple slot for outer tuples
* hj_HashTupleSlot tuple slot for hashed tuples
* hj_NullInnerTupleSlot prepared null tuple for left outer joins
+ * hj_FirstOuterTupleSlot first tuple retrieved from outer plan
* hj_NeedNewOuter true if need new outer tuple on next call
* hj_MatchedOuter true if found a join match for current outer
- * hj_hashdone true if hash-table-build phase is done
+ * hj_OuterNotEmpty true if outer relation known not empty
* ----------------
*/
+
+/* these structs are defined in executor/hashjoin.h: */
+typedef struct HashJoinTupleData *HashJoinTuple;
+typedef struct HashJoinTableData *HashJoinTable;
+
typedef struct HashJoinState
{
JoinState js; /* its first field is NodeTag */
List *hashclauses; /* list of ExprState nodes */
HashJoinTable hj_HashTable;
+ uint32 hj_CurHashValue;
int hj_CurBucketNo;
HashJoinTuple hj_CurTuple;
List *hj_OuterHashKeys; /* list of ExprState nodes */
TupleTableSlot *hj_OuterTupleSlot;
TupleTableSlot *hj_HashTupleSlot;
TupleTableSlot *hj_NullInnerTupleSlot;
+ TupleTableSlot *hj_FirstOuterTupleSlot;
bool hj_NeedNewOuter;
bool hj_MatchedOuter;
- bool hj_hashdone;
+ bool hj_OuterNotEmpty;
} HashJoinState;
typedef struct MaterialState
{
ScanState ss; /* its first field is NodeTag */
- void *tuplestorestate; /* private state of tuplestore.c */
+ int eflags; /* capability flags to pass to tuplestore */
bool eof_underlying; /* reached end of underlying plan? */
+ Tuplestorestate *tuplestorestate;
} MaterialState;
/* ----------------
typedef struct SortState
{
ScanState ss; /* its first field is NodeTag */
+ bool randomAccess; /* need random access to sort output? */
+ bool bounded; /* is the result set bounded? */
+ int64 bound; /* if bounded, how many tuples are needed */
bool sort_Done; /* sort completed yet? */
+ bool bounded_Done; /* value of bounded we did the sort with */
+ int64 bound_Done; /* value of bound we did the sort with */
void *tuplesortstate; /* private state of tuplesort.c */
} SortState;
{
ScanState ss; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
- HeapTuple grp_firstTuple; /* copy of first tuple of current group */
bool grp_done; /* indicates completion of Group scan */
} GroupState;
HeapTuple grp_firstTuple; /* copy of first tuple of current group */
/* these fields are used in AGG_HASHED mode: */
TupleHashTable hashtable; /* hash table with one entry per group */
+ TupleTableSlot *hashslot; /* slot for loading hash table */
+ List *hash_needed; /* list of columns needed in hash table */
bool table_filled; /* hash table filled yet? */
TupleHashIterator hashiter; /* for iterating through hash table */
} AggState;
+/* ----------------
+ * WindowAggState information
+ * ----------------
+ */
+/* these structs are private in nodeWindowAgg.c: */
+typedef struct WindowStatePerFuncData *WindowStatePerFunc;
+typedef struct WindowStatePerAggData *WindowStatePerAgg;
+
+typedef struct WindowAggState
+{
+ ScanState ss; /* its first field is NodeTag */
+
+ /* these fields are filled in by ExecInitExpr: */
+ List *funcs; /* all WindowFunc nodes in targetlist */
+ int numfuncs; /* total number of window functions */
+ int numaggs; /* number that are plain aggregates */
+
+ WindowStatePerFunc perfunc; /* per-window-function information */
+ WindowStatePerAgg peragg; /* per-plain-aggregate information */
+ FmgrInfo *partEqfunctions; /* equality funcs for partition columns */
+ FmgrInfo *ordEqfunctions; /* equality funcs for ordering columns */
+ Tuplestorestate *buffer; /* stores rows of current partition */
+ int current_ptr; /* read pointer # for current */
+ int agg_ptr; /* read pointer # for aggregates */
+ int64 spooled_rows; /* total # of rows in buffer */
+ int64 currentpos; /* position of current row in partition */
+ int64 frametailpos; /* current frame tail position */
+ int64 aggregatedupto; /* rows before this one are aggregated */
+
+ MemoryContext wincontext; /* context for partition-lifespan data */
+ ExprContext *tmpcontext; /* short-term evaluation context */
+
+ bool all_done; /* true if the scan is finished */
+ bool partition_spooled; /* true if all tuples in current partition
+ * have been spooled into tuplestore */
+ bool more_partitions; /* true if there's more partitions after
+ * this one */
+ bool frametail_valid; /* true if frametailpos is known up to date
+ * for current row */
+
+ TupleTableSlot *first_part_slot; /* first tuple of current or next
+ * partition */
+
+ /* temporary slots for tuples fetched back from tuplestore */
+ TupleTableSlot *agg_row_slot;
+ TupleTableSlot *temp_slot_1;
+ TupleTableSlot *temp_slot_2;
+} WindowAggState;
+
/* ----------------
* UniqueState information
*
* Unique nodes are used "on top of" sort nodes to discard
* duplicate tuples returned from the sort phase. Basically
* all it does is compare the current tuple from the subplan
- * with the previously fetched tuple stored in priorTuple.
+ * with the previously fetched tuple (stored in its result slot).
* If the two are identical in all interesting fields, then
* we just fetch another tuple from the sort and try again.
* ----------------
{
PlanState ps; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
- HeapTuple priorTuple; /* most recently returned tuple, or NULL */
MemoryContext tempContext; /* short-term context for comparisons */
} UniqueState;
/* ----------------
* SetOpState information
*
- * SetOp nodes are used "on top of" sort nodes to discard
- * duplicate tuples returned from the sort phase. These are
- * more complex than a simple Unique since we have to count
- * how many duplicates to return.
+ * Even in "sorted" mode, SetOp nodes are more complex than a simple
+ * Unique, since we have to count how many duplicates to return. But
+ * we also support hashing, so this is really more like a cut-down
+ * form of Agg.
* ----------------
*/
+/* this struct is private in nodeSetOp.c: */
+typedef struct SetOpStatePerGroupData *SetOpStatePerGroup;
+
typedef struct SetOpState
{
PlanState ps; /* its first field is NodeTag */
- FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
- bool subplan_done; /* has subplan returned EOF? */
- long numLeft; /* number of left-input dups of cur group */
- long numRight; /* number of right-input dups of cur group */
+ FmgrInfo *eqfunctions; /* per-grouping-field equality fns */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ bool setop_done; /* indicates completion of output scan */
long numOutput; /* number of dups left to output */
MemoryContext tempContext; /* short-term context for comparisons */
+ /* these fields are used in SETOP_SORTED mode: */
+ SetOpStatePerGroup pergroup; /* per-group working state */
+ HeapTuple grp_firstTuple; /* copy of first tuple of current group */
+ /* these fields are used in SETOP_HASHED mode: */
+ TupleHashTable hashtable; /* hash table with one entry per group */
+ MemoryContext tableContext; /* memory context containing hash table */
+ bool table_filled; /* hash table filled yet? */
+ TupleHashIterator hashiter; /* for iterating through hash table */
} SetOpState;
/* ----------------
typedef enum
{
LIMIT_INITIAL, /* initial state for LIMIT node */
+ LIMIT_RESCAN, /* rescan after recomputing parameters */
LIMIT_EMPTY, /* there are no returnable rows */
LIMIT_INWINDOW, /* have returned a row in the window */
LIMIT_SUBPLANEOF, /* at EOF of subplan (within window) */
PlanState ps; /* its first field is NodeTag */
ExprState *limitOffset; /* OFFSET parameter, or NULL if none */
ExprState *limitCount; /* COUNT parameter, or NULL if none */
- long offset; /* current OFFSET value */
- long count; /* current COUNT, if any */
+ int64 offset; /* current OFFSET value */
+ int64 count; /* current COUNT, if any */
bool noCount; /* if true, ignore count */
LimitStateCond lstate; /* state machine status, as above */
- long position; /* 1-based index of last tuple returned */
+ int64 position; /* 1-based index of last tuple returned */
TupleTableSlot *subSlot; /* tuple last obtained from subplan */
} LimitState;