]> granicus.if.org Git - postgresql/blobdiff - src/include/nodes/execnodes.h
Add an "argisrow" field to NullTest nodes, following a plan made way back in
[postgresql] / src / include / nodes / execnodes.h
index 325bf8768002185c6f90a9e79f8f381d36f9cfb4..12cfcc4fdfa31304127ddf85cca17f5bd49e46fb 100644 (file)
@@ -4,24 +4,25 @@
  *       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
  *
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.116 2004/05/10 22:44:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.215 2010/01/01 23:03:10 tgl 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/tidbitmap.h"
 #include "utils/hsearch.h"
+#include "utils/rel.h"
+#include "utils/snapshot.h"
 #include "utils/tuplestore.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?
+ *             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
@@ -51,7 +61,13 @@ typedef struct IndexInfo
        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;
+       bool            ii_BrokenHotChain;
 } IndexInfo;
 
 /* ----------------
@@ -109,9 +125,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;
@@ -121,7 +140,7 @@ typedef struct ExprContext
        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 */
@@ -141,12 +160,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;
 
 /*
@@ -176,20 +198,37 @@ typedef struct ReturnSetInfo
  *             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).  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.
  *
- *             targetlist              target list for projection
+ *             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 (non-Var expressions only)
  *             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
+ *             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 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)
  * ----------------
  */
 typedef struct ProjectionInfo
@@ -198,9 +237,15 @@ typedef struct ProjectionInfo
        List       *pi_targetlist;
        ExprContext *pi_exprContext;
        TupleTableSlot *pi_slot;
-       Datum      *pi_tupValues;
-       char       *pi_tupNulls;
        ExprDoneCond *pi_itemIsDone;
+       bool            pi_directMap;
+       int                     pi_numSimpleVars;
+       int                *pi_varSlotOffsets;
+       int                *pi_varNumbers;
+       int                *pi_varOutputCols;
+       int                     pi_lastInnerVar;
+       int                     pi_lastOuterVar;
+       int                     pi_lastScanVar;
 } ProjectionInfo;
 
 /* ----------------
@@ -209,39 +254,35 @@ typedef struct 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;
 
 /* ----------------
@@ -259,8 +300,11 @@ typedef struct JunkFilter
  *             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
+ *             projectReturning                for computing a RETURNING list
  * ----------------
  */
 typedef struct ResultRelInfo
@@ -273,8 +317,11 @@ typedef struct ResultRelInfo
        IndexInfo **ri_IndexRelationInfo;
        TriggerDesc *ri_TrigDesc;
        FmgrInfo   *ri_TrigFunctions;
+       List      **ri_TrigWhenExprs;
+       struct Instrumentation *ri_TrigInstrument;
        List      **ri_ConstraintExprs;
        JunkFilter *ri_junkFilter;
+       ProjectionInfo *ri_projectReturning;
 } ResultRelInfo;
 
 /* ----------------
@@ -290,16 +337,24 @@ typedef struct EState
        /* Basic state for all query types: */
        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 */
+       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;
 
        /* 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 */
-       JunkFilter *es_junkFilter;      /* currently active junk filter */
-       Relation        es_into_relation_descriptor;    /* for SELECT INTO */
+       ResultRelInfo *es_result_relation_info;         /* currently active array elt */
+
+       /* 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_oldtup_slot;    /* for trigger old tuples */
 
        /* Parameter info: */
        ParamListInfo es_param_list_info;       /* values of external params */
@@ -308,40 +363,85 @@ typedef struct EState
        /* 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_rowMark;         /* not good place, but there is no other */
 
-       bool            es_instrument;  /* true requests runtime instrumentation */
-       bool            es_select_into; /* true if doing SELECT INTO */
+       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 */
 
        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 */
-       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;
 
 
+/*
+ * 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 suitably locked relation */
+       Index           rti;                    /* its range table index */
+       Index           prti;                   /* parent range table index, if child */
+       RowMarkType     markType;               /* see enum in nodes/plannodes.h */
+       bool            noWait;                 /* NOWAIT option */
+       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;
+
+
 /* ----------------------------------------------------------------
  *                              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;
@@ -350,7 +450,7 @@ typedef struct TupleHashTableData *TupleHashTable;
 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 */
 
@@ -359,18 +459,34 @@ typedef struct TupleHashTableData
        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))
 
@@ -403,15 +519,15 @@ typedef HASH_SEQ_STATUS TupleHashIterator;
 typedef struct ExprState ExprState;
 
 typedef Datum (*ExprStateEvalFunc) (ExprState *expression,
-                                                                       ExprContext *econtext,
-                                                                       bool *isNull,
-                                                                       ExprDoneCond *isDone);
+                                                                                               ExprContext *econtext,
+                                                                                               bool *isNull,
+                                                                                               ExprDoneCond *isDone);
 
 struct ExprState
 {
        NodeTag         type;
        Expr       *expr;                       /* associated Expr node */
-       ExprStateEvalFunc evalfunc;     /* routine to run to execute node */
+       ExprStateEvalFunc evalfunc; /* routine to run to execute node */
 };
 
 /* ----------------
@@ -434,10 +550,21 @@ typedef struct GenericExprState
 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
  *
@@ -473,14 +600,31 @@ typedef struct FuncExprState
        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
@@ -491,21 +635,22 @@ 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.
+        * 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 */
 
        /*
         * 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 */
 
        /*
-        * Current argument data for a set-valued function; contains valid
-        * data only if setArgsValid is true.
+        * Current argument data for a set-valued function; contains valid data
+        * only if setArgsValid is true.
         */
        FunctionCallInfoData setArgs;
 } FuncExprState;
@@ -543,11 +688,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 */
-       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 */
@@ -559,10 +702,23 @@ typedef struct SubPlanState
        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
  * ----------------
@@ -574,6 +730,60 @@ typedef struct FieldSelectState
        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 */
+       /* use "struct" so we needn't include tupconvert.h here */
+       struct TupleConversionMap *map;
+       bool            initialized;
+} ConvertRowtypeExprState;
+
 /* ----------------
  *             CaseExprState node
  * ----------------
@@ -624,6 +834,18 @@ typedef struct RowExprState
        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
  * ----------------
@@ -634,6 +856,40 @@ typedef struct CoalesceExprState
        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 */
+       List       *args;                       /* ExprStates for other arguments */
+} XmlExprState;
+
+/* ----------------
+ *             NullTestState node
+ * ----------------
+ */
+typedef struct NullTestState
+{
+       ExprState       xprstate;
+       ExprState  *arg;                        /* input expression */
+       /* used only if input is of composite type: */
+       TupleDesc       argdesc;                /* tupdesc for most recent input */
+} NullTestState;
+
 /* ----------------
  *             CoerceToDomainState node
  * ----------------
@@ -689,25 +945,24 @@ typedef struct PlanState
 
        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 */
 
        /*
@@ -718,7 +973,6 @@ 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 */
@@ -736,6 +990,21 @@ typedef struct 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
@@ -749,13 +1018,26 @@ typedef struct ResultState
        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
@@ -764,10 +1046,56 @@ typedef struct AppendState
        PlanState **appendplans;        /* array of PlanStates for my inputs */
        int                     as_nplans;
        int                     as_whichplan;
-       int                     as_firstplan;
-       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
  * ----------------------------------------------------------------
@@ -801,57 +1129,126 @@ typedef struct ScanState
  */
 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 */
+       bool            key_toastable;  /* is expr's result a toastable datatype? */
+} 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
  *
- *             indxqualorig       execution state for indxqualorig expressions
- *             NumIndices                 number of indices in this scan
- *             IndexPtr                   current index in use
- *             MarkIndexPtr       IndexPtr for marked scan point
- *             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
- *             LossyQuals                 ptr to array of qual lists for lossy operators
- *             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       *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;
-       List      **iss_LossyQuals;
-       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)
+ *             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;
+
 /* ----------------
  *      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;
@@ -863,17 +1260,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;
 
 /* ----------------
@@ -882,6 +1275,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
@@ -890,11 +1284,77 @@ typedef struct SubqueryScanState
 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
  * ----------------------------------------------------------------
@@ -932,25 +1392,35 @@ typedef struct NestLoopState
 /* ----------------
  *      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;
@@ -958,34 +1428,47 @@ typedef struct MergeJoinState
        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
- *             hj_CurBucketNo                  bucket# for current outer tuple
+ *                                                             (NULL if table not built yet)
+ *             hj_CurHashValue                 hash value 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
- *                                                             (CurBucketNo and CurTuple are meaningless
- *                                                              unless OuterTupleSlot is nonempty!)
+ *                                                             (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
  *             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;
+       int                     hj_CurSkewBucketNo;
        HashJoinTuple hj_CurTuple;
        List       *hj_OuterHashKeys;           /* list of ExprState nodes */
        List       *hj_InnerHashKeys;           /* list of ExprState nodes */
@@ -993,9 +1476,10 @@ typedef struct HashJoinState
        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;
 
 
@@ -1016,8 +1500,9 @@ typedef struct 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;
 
 /* ----------------
@@ -1027,7 +1512,12 @@ typedef struct 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;
 
@@ -1039,7 +1529,6 @@ typedef struct GroupState
 {
        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;
 
@@ -1075,17 +1564,69 @@ typedef struct AggState
        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.
  * ----------------
@@ -1094,7 +1635,6 @@ typedef struct UniqueState
 {
        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;
 
@@ -1113,23 +1653,46 @@ 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;
 
+/* ----------------
+ *      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
  *
@@ -1145,6 +1708,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) */
@@ -1157,11 +1721,11 @@ typedef struct LimitState
        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;