]> granicus.if.org Git - postgresql/blobdiff - src/include/nodes/execnodes.h
Update copyright for 2009.
[postgresql] / src / include / nodes / execnodes.h
index b576f4610e3e75e7b7e84de5bb6b52b676db18ee..4b2b64c300ee0540ba561903b1428c4d94d8ffac 100644 (file)
@@ -4,21 +4,25 @@
  *       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
@@ -50,7 +59,9 @@ 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;
 
 /* ----------------
@@ -108,9 +119,12 @@ typedef struct ExprContext
        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;
@@ -140,12 +154,15 @@ typedef enum
 /*
  * 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;
 
 /*
@@ -302,7 +319,10 @@ typedef struct EState
        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 */
@@ -310,11 +330,10 @@ typedef struct EState
        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 */
@@ -328,14 +347,14 @@ typedef struct EState
        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
@@ -352,14 +371,20 @@ typedef struct EState
 } 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;
 
 
@@ -394,7 +419,7 @@ typedef struct TupleHashTableData
        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 */
@@ -408,8 +433,20 @@ typedef struct 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))
 
@@ -477,6 +514,17 @@ typedef struct AggrefExprState
        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
  *
@@ -513,13 +561,29 @@ typedef struct FuncExprState
 
        /*
         * 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
@@ -531,14 +595,15 @@ typedef struct FuncExprState
        /*
         * 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 */
 
@@ -582,11 +647,9 @@ typedef struct BoolExprState
 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 */
@@ -598,12 +661,23 @@ typedef struct SubPlanState
        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
  * ----------------
@@ -627,6 +701,33 @@ typedef struct FieldStoreState
        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
  * ----------------
@@ -735,7 +836,7 @@ typedef struct XmlExprState
 {
        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;
 
@@ -807,7 +908,7 @@ typedef struct PlanState
 
        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 */
 
@@ -835,12 +936,11 @@ typedef struct PlanState
        /*
         * 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;
 
 /* ----------------
@@ -885,6 +985,32 @@ typedef struct AppendState
        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
  * ----------------
@@ -1040,6 +1166,7 @@ typedef struct BitmapHeapScanState
 /* ----------------
  *      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)
@@ -1049,6 +1176,7 @@ typedef struct TidScanState
 {
        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;
@@ -1060,17 +1188,13 @@ typedef struct TidScanState
  *      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;
 
 /* ----------------
@@ -1079,6 +1203,7 @@ typedef struct 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
@@ -1087,6 +1212,7 @@ typedef struct SubqueryScanState
 typedef struct FunctionScanState
 {
        ScanState       ss;                             /* its first field is NodeTag */
+       int                     eflags;
        TupleDesc       tupdesc;
        Tuplestorestate *tuplestorestate;
        ExprState  *funcexpr;
@@ -1120,6 +1246,43 @@ typedef struct ValuesScanState
        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
  * ----------------------------------------------------------------
@@ -1160,6 +1323,7 @@ typedef struct NestLoopState
  *             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
@@ -1182,6 +1346,7 @@ typedef struct MergeJoinState
        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;
@@ -1261,9 +1426,9 @@ typedef struct HashJoinState
 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;
 
 /* ----------------
@@ -1274,7 +1439,11 @@ 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;
 
@@ -1327,6 +1496,55 @@ typedef struct AggState
        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
  *
@@ -1360,21 +1578,31 @@ typedef struct HashState
 /* ----------------
  *      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;
 
 /* ----------------
@@ -1392,6 +1620,7 @@ typedef struct 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) */