* definitions for executor state nodes
*
*
- * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.168 2007/02/20 17:32:17 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 "access/genam.h"
+#include "access/heapam.h"
+#include "access/skey.h"
#include "nodes/params.h"
-#include "nodes/plannodes.h"
-#include "nodes/tidbitmap.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;
/*
* 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;
/*
ScanDirection es_direction; /* current scan direction */
Snapshot es_snapshot; /* time qual to use */
Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
- List *es_range_table; /* List of RangeTableEntrys */
+ 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 */
ResultRelInfo *es_result_relation_info; /* currently active array elt */
JunkFilter *es_junkFilter; /* currently active junk filter */
+ /* Stuff used for firing triggers: */
+ List *es_trig_target_relations; /* trigger-only ResultRelInfos */
TupleTableSlot *es_trig_tuple_slot; /* for trigger output tuples */
- Relation es_into_relation_descriptor; /* for SELECT INTO */
- bool es_into_relation_use_wal;
-
/* Parameter info: */
ParamListInfo es_param_list_info; /* values of external params */
ParamExecData *es_param_exec_vals; /* values of internal params */
Oid es_lastoid; /* last oid processed (by INSERT) */
List *es_rowMarks; /* not good place, but there is no other */
- bool es_is_subquery; /* true if subquery (es_query_cxt not mine) */
-
bool es_instrument; /* true requests runtime instrumentation */
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
} EState;
-/* es_rowMarks is a list of these structs: */
+/*
+ * 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;
HTAB *hashtab; /* underlying dynahash table */
int numCols; /* number of columns in lookup key */
AttrNumber *keyColIdx; /* attr numbers of key columns */
- FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */
+ FmgrInfo *tab_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 */
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))
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
*
/*
* Function manager's lookup info for the target function. If func.fn_oid
- * is InvalidOid, we haven't initialized it yet.
+ * 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.
+ * only when setArgsValid is true or funcResultStore isn't NULL.
*/
bool setHasSetArg; /* some argument returns a set */
/*
* Flag to remember whether we have registered a shutdown callback for
- * this FuncExprState. We do so only if setArgsValid has been true at
- * least once (since all the callback is for is to clear setArgsValid).
+ * 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 */
typedef struct SubPlanState
{
ExprState xprstate;
- EState *sub_estate; /* subselect plan has its own EState */
struct PlanState *planstate; /* subselect plan's state tree */
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 *tab_hash_funcs; /* hash functions for table datatype(s) */
+ 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 *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
* ----------------
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
* ----------------
{
ExprState xprstate;
List *named_args; /* ExprStates for named arguments */
- FmgrInfo *named_outfuncs; /* array of output fns for named arguments */
+ FmgrInfo *named_outfuncs; /* array of output fns for named arguments */
List *args; /* ExprStates for other arguments */
} XmlExprState;
Plan *plan; /* associated Plan node */
- EState *state; /* at execution time, state's of individual
+ EState *state; /* at execution time, states of individual
* nodes point to one EState for the whole
* top-level plan */
/*
* 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
* ----------------
/* ----------------
* TidScanState information
*
+ * isCurrentOf scan has a CurrentOfExpr qual
* NumTids number of tids in this scan
* TidPtr index of currently fetched tid
* TidList evaluated item pointers (array of size NumTids)
{
ScanState ss; /* its first field is NodeTag */
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;
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
* ----------------------------------------------------------------
* 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
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;
typedef struct MaterialState
{
ScanState ss; /* its first field is NodeTag */
- bool randomAccess; /* need random access to subplan output? */
+ int eflags; /* capability flags to pass to tuplestore */
bool eof_underlying; /* reached end of underlying plan? */
- void *tuplestorestate; /* private state of tuplestore.c */
+ Tuplestorestate *tuplestorestate;
} MaterialState;
/* ----------------
{
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;
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
*
/* ----------------
* 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) */