* definitions for executor state nodes
*
*
- * Portions Copyright (c) 1996-2008, 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.193 2008/10/29 00:00:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.215 2010/01/01 23:03:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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"
* ExpressionsState exec state for expressions, or NIL if none
* Predicate partial-index predicate, or NIL if none
* PredicateState exec state for predicate, or NIL if none
+ * ExclusionOps Per-column exclusion operators, or NULL if none
+ * ExclusionProcs Underlying function OIDs for ExclusionOps
+ * ExclusionStrats Opclass strategy numbers for ExclusionOps
* Unique is it a unique index?
* ReadyForInserts is it valid for inserts?
* Concurrent are we doing a concurrent index build?
List *ii_ExpressionsState; /* list of ExprState */
List *ii_Predicate; /* list of Expr */
List *ii_PredicateState; /* list of ExprState */
+ Oid *ii_ExclusionOps; /* array with one entry per column */
+ Oid *ii_ExclusionProcs; /* array with one entry per column */
+ uint16 *ii_ExclusionStrats; /* array with one entry per column */
bool ii_Unique;
bool ii_ReadyForInserts;
bool ii_Concurrent;
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_Random = 0x04 /* Tuplestore needs randomAccess */
+ SFRM_Materialize_Random = 0x04, /* Tuplestore needs randomAccess */
+ SFRM_Materialize_Preferred = 0x08 /* caller prefers Tuplestore */
} SetFunctionReturnMode;
/*
*
* 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.
+ * look like that). And top-level tlists are often mostly Vars too.
+ * We therefore optimize execution of simple-Var tlist entries.
+ * The pi_targetlist list actually contains only the tlist entries that
+ * aren't simple Vars, while those that are Vars are processed using the
+ * varSlotOffsets/varNumbers/varOutputCols arrays.
+ *
+ * The lastXXXVar fields are used to optimize fetching of fields from
+ * input tuples: they let us do a slot_getsomeattrs() call to ensure
+ * that all needed attributes are extracted in one pass.
*
- * targetlist target list for projection
+ * targetlist target list for projection (non-Var expressions only)
* exprContext expression context in which to evaluate targetlist
* slot slot to place projection result in
- * itemIsDone workspace for ExecProject
- * isVarList TRUE if simple-Var-list optimization applies
+ * itemIsDone workspace array for ExecProject
+ * directMap true if varOutputCols[] is an identity map
+ * numSimpleVars number of simple Vars found in original tlist
* varSlotOffsets array indicating which slot each simple Var is from
- * varNumbers array indicating attr numbers of simple Vars
+ * varNumbers array containing input attr numbers of simple Vars
+ * varOutputCols array containing output attr numbers of simple Vars
* lastInnerVar highest attnum from inner tuple slot (0 if none)
* lastOuterVar highest attnum from outer tuple slot (0 if none)
* lastScanVar highest attnum from scan tuple slot (0 if none)
ExprContext *pi_exprContext;
TupleTableSlot *pi_slot;
ExprDoneCond *pi_itemIsDone;
- bool pi_isVarList;
+ bool pi_directMap;
+ int pi_numSimpleVars;
int *pi_varSlotOffsets;
int *pi_varNumbers;
+ int *pi_varOutputCols;
int pi_lastInnerVar;
int pi_lastOuterVar;
int pi_lastScanVar;
* IndexRelationInfo array of key/attr info for indices
* TrigDesc triggers to be fired, if any
* TrigFunctions cached lookup info for trigger functions
+ * TrigWhenExprs array of trigger WHEN expr states
* TrigInstrument optional runtime measurements for triggers
* ConstraintExprs array of constraint-checking expr states
* junkFilter for removing junk attributes from tuples
IndexInfo **ri_IndexRelationInfo;
TriggerDesc *ri_TrigDesc;
FmgrInfo *ri_TrigFunctions;
+ List **ri_TrigWhenExprs;
struct Instrumentation *ri_TrigInstrument;
List **ri_ConstraintExprs;
JunkFilter *ri_junkFilter;
Snapshot es_snapshot; /* time qual to use */
Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
List *es_range_table; /* List of RangeTblEntry */
+ PlannedStmt *es_plannedstmt; /* link to top of plan tree */
+
+ JunkFilter *es_junkFilter; /* top-level junk filter, if any */
/* If query can insert/delete tuples, the command ID to mark them with */
CommandId es_output_cid;
ResultRelInfo *es_result_relations; /* array of ResultRelInfos */
int es_num_result_relations; /* length of array */
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 */
+ TupleTableSlot *es_trig_tuple_slot; /* for trigger output tuples */
+ TupleTableSlot *es_trig_oldtup_slot; /* for trigger old tuples */
/* Parameter info: */
ParamListInfo es_param_list_info; /* values of external params */
/* Other working state: */
MemoryContext es_query_cxt; /* per-query context in which EState lives */
- TupleTable es_tupleTable; /* Array of TupleTableSlots */
+ List *es_tupleTable; /* List of TupleTableSlots */
+
+ List *es_rowMarks; /* List of ExecRowMarks */
uint32 es_processed; /* # of tuples processed */
Oid es_lastoid; /* last oid processed (by INSERT) */
- List *es_rowMarks; /* not good place, but there is no other */
- bool es_instrument; /* true requests runtime instrumentation */
+ int es_instrument; /* OR of InstrumentOption flags */
bool es_select_into; /* true if doing SELECT INTO */
bool es_into_oids; /* true to generate OIDs in SELECT INTO */
*/
ExprContext *es_per_tuple_exprcontext;
- /* Below is to re-evaluate plan qual in READ COMMITTED mode */
- 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? */
+ /*
+ * These fields are for re-evaluating plan quals when an updated tuple is
+ * substituted in READ COMMITTED mode. es_epqTuple[] contains tuples
+ * that scan plan nodes should return instead of whatever they'd normally
+ * return, or NULL if nothing to return; es_epqTupleSet[] is true if a
+ * particular array entry is valid; and es_epqScanDone[] is state to
+ * remember if the tuple has been returned already. Arrays are of size
+ * list_length(es_range_table) and are indexed by scan node scanrelid - 1.
+ */
+ HeapTuple *es_epqTuple; /* array of EPQ substitute tuples */
+ bool *es_epqTupleSet; /* true if EPQ tuple is provided */
+ bool *es_epqScanDone; /* true if EPQ tuple has been fetched */
} EState;
-/* es_rowMarks is a list of these structs: */
+/*
+ * ExecRowMark -
+ * runtime representation of FOR UPDATE/SHARE clauses
+ *
+ * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we should have an
+ * ExecRowMark for each non-target relation in the query (except inheritance
+ * parent RTEs, which can be ignored at runtime). See PlanRowMark for details
+ * about most of the fields.
+ *
+ * es_rowMarks is a list of these structs. Each LockRows node has its own
+ * list, which is the subset of locks that it is supposed to enforce; note
+ * that the per-node lists point to the same structs that are in the global
+ * list.
+ */
typedef struct ExecRowMark
{
- Relation relation; /* opened and RowShareLock'd relation */
+ Relation relation; /* opened and suitably locked relation */
Index rti; /* its range table index */
- bool forUpdate; /* true = FOR UPDATE, false = FOR SHARE */
+ Index prti; /* parent range table index, if child */
+ RowMarkType markType; /* see enum in nodes/plannodes.h */
bool noWait; /* NOWAIT option */
- AttrNumber ctidAttNo; /* resno of its ctid junk attribute */
+ AttrNumber ctidAttNo; /* resno of ctid junk attribute, if any */
+ AttrNumber toidAttNo; /* resno of tableoid junk attribute, if any */
+ AttrNumber wholeAttNo; /* resno of whole-row junk attribute, if any */
+ ItemPointerData curCtid; /* ctid of currently locked tuple, if any */
} ExecRowMark;
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
*
FmgrInfo func;
/*
- * For a set-returning function (SRF) that returns a tuplestore, we
- * keep the tuplestore here and dole out the result rows one at a time.
- * The slot holds the row currently being returned.
+ * 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.
+ * output. If so, it's stored here.
*/
TupleDesc funcResultDesc;
- bool funcReturnsTuple; /* valid when funcResultDesc isn't NULL */
+ bool funcReturnsTuple; /* valid when funcResultDesc isn't
+ * NULL */
/*
* We need to store argument values across calls when evaluating a SRF
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;
+ /* use "struct" so we needn't include tupconvert.h here */
+ struct TupleConversionMap *map;
+ bool initialized;
} ConvertRowtypeExprState;
/* ----------------
{
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;
{
ExprState xprstate;
ExprState *arg; /* input expression */
- bool argisrow; /* T if input is of a composite type */
- /* used only if argisrow: */
+ /* used only if input is of composite type: */
TupleDesc argdesc; /* tupdesc for most recent input */
} NullTestState;
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;
/* ----------------
#define innerPlanState(node) (((PlanState *)(node))->righttree)
#define outerPlanState(node) (((PlanState *)(node))->lefttree)
+/*
+ * EPQState is state for executing an EvalPlanQual recheck on a candidate
+ * tuple in ModifyTable or LockRows. The estate and planstate fields are
+ * NULL if inactive.
+ */
+typedef struct EPQState
+{
+ EState *estate; /* subsidiary EState */
+ PlanState *planstate; /* plan state tree ready to be executed */
+ TupleTableSlot *origslot; /* original output tuple to be rechecked */
+ Plan *plan; /* plan tree to be executed */
+ List *rowMarks; /* ExecRowMarks (non-locking only) */
+ int epqParam; /* ID of Param to force scan node re-eval */
+} EPQState;
+
/* ----------------
* ResultState information
bool rs_checkqual; /* do we need to check the qual? */
} ResultState;
+/* ----------------
+ * ModifyTableState information
+ * ----------------
+ */
+typedef struct ModifyTableState
+{
+ PlanState ps; /* its first field is NodeTag */
+ CmdType operation;
+ PlanState **mt_plans; /* subplans (one per target rel) */
+ int mt_nplans; /* number of plans in the array */
+ int mt_whichplan; /* which one is being executed (0..n-1) */
+ EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
+ bool fireBSTriggers; /* do we need to fire stmt triggers? */
+} ModifyTableState;
+
/* ----------------
* AppendState information
*
- * nplans how many plans are in the list
+ * nplans how many plans are in the array
* whichplan which plan is being executed (0 .. n-1)
- * firstplan first plan to execute (usually 0)
- * lastplan last plan to execute (usually n-1)
* ----------------
*/
typedef struct AppendState
PlanState **appendplans; /* array of PlanStates for my inputs */
int as_nplans;
int as_whichplan;
- int as_firstplan;
- int as_lastplan;
} AppendState;
/* ----------------
FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
MemoryContext tempContext; /* short-term context for comparisons */
TupleHashTable hashtable; /* hash table for tuples already seen */
- MemoryContext tableContext; /* memory context containing hash table */
+ MemoryContext tableContext; /* memory context containing hash table */
} RecursiveUnionState;
/* ----------------
{
ScanKey scan_key; /* scankey to put value into */
ExprState *key_expr; /* expr to evaluate to get value */
+ bool key_toastable; /* is expr's result a toastable datatype? */
} IndexRuntimeKeyInfo;
typedef struct
*
* bitmapqualorig execution state for bitmapqualorig expressions
* tbm bitmap obtained from child index scan(s)
+ * tbmiterator iterator for scanning current pages
* tbmres current-page data
+ * prefetch_iterator iterator for prefetching ahead of current page
+ * prefetch_pages # pages prefetch iterator is ahead of current
+ * prefetch_target target prefetch distance
* ----------------
*/
typedef struct BitmapHeapScanState
ScanState ss; /* its first field is NodeTag */
List *bitmapqualorig;
TIDBitmap *tbm;
+ TBMIterator *tbmiterator;
TBMIterateResult *tbmres;
+ TBMIterator *prefetch_iterator;
+ int prefetch_pages;
+ int prefetch_target;
} BitmapHeapScanState;
/* ----------------
/* 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 */
+ 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
+ * a RecursiveUnion node. We locate the RecursiveUnion node
* during executor startup.
* ----------------
*/
* 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_CurBucketNo regular bucket# for current outer tuple
+ * hj_CurSkewBucketNo skew bucket# for current outer tuple
* hj_CurTuple last inner tuple matched to current outer
* tuple, or NULL if starting search
- * (CurHashValue, CurBucketNo and CurTuple are
- * undefined if OuterTupleSlot is empty!)
+ * (hj_CurXXX variables 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
HashJoinTable hj_HashTable;
uint32 hj_CurHashValue;
int hj_CurBucketNo;
+ int hj_CurSkewBucketNo;
HashJoinTuple hj_CurTuple;
List *hj_OuterHashKeys; /* list of ExprState nodes */
List *hj_InnerHashKeys; /* list of ExprState nodes */
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
*
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 */
+ MemoryContext tableContext; /* memory context containing hash table */
bool table_filled; /* hash table filled yet? */
TupleHashIterator hashiter; /* for iterating through hash table */
} SetOpState;
+/* ----------------
+ * LockRowsState information
+ *
+ * LockRows nodes are used to enforce FOR UPDATE/FOR SHARE locking.
+ * ----------------
+ */
+typedef struct LockRowsState
+{
+ PlanState ps; /* its first field is NodeTag */
+ List *lr_rowMarks; /* List of ExecRowMarks */
+ EPQState lr_epqstate; /* for evaluating EvalPlanQual rechecks */
+} LockRowsState;
+
/* ----------------
* LimitState information
*