]> granicus.if.org Git - postgresql/blobdiff - src/include/nodes/execnodes.h
Teach tid-scan code to make use of "ctid = ANY (array)" clauses, so that
[postgresql] / src / include / nodes / execnodes.h
index 0967bef24ba9437360c5142ffc6f770107c9aa5a..e9fb41f653a06207588eebf11aa5d4d6c947d29b 100644 (file)
@@ -4,10 +4,10 @@
  *       definitions for executor state nodes
  *
  *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: execnodes.h,v 1.58 2001/05/07 00:43:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.144 2005/11/26 22:14:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define EXECNODES_H
 
 #include "access/relscan.h"
-#include "access/sdir.h"
-#include "executor/hashjoin.h"
 #include "executor/tuptable.h"
 #include "fmgr.h"
+#include "nodes/bitmapset.h"
 #include "nodes/params.h"
-#include "nodes/primnodes.h"
+#include "nodes/plannodes.h"
+#include "nodes/tidbitmap.h"
+#include "utils/hsearch.h"
+#include "utils/tuplestore.h"
+
 
 /* ----------------
  *       IndexInfo information
  *
- *             this class holds the information needed to construct new index
+ *             this struct holds the information needed to construct new index
  *             entries for a particular index.  Used for both index_build and
  *             retail creation of index entries.
  *
  *             NumIndexAttrs           number of columns in this index
- *                                                     (1 if a func. index, else same as NumKeyAttrs)
- *             NumKeyAttrs                     number of key attributes for this index
- *                                                     (ie, number of attrs from underlying relation)
  *             KeyAttrNumbers          underlying-rel attribute numbers used as keys
- *             Predicate                       partial-index predicate, or NULL if none
- *             FuncOid                         OID of function, or InvalidOid if not f. index
- *             FuncInfo                        fmgr lookup data for function, if FuncOid valid
+ *                                                     (zeroes indicate expressions)
+ *             Expressions                     expr trees for expression entries, or NIL if none
+ *             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
  *             Unique                          is it a unique index?
  * ----------------
  */
@@ -44,14 +46,29 @@ typedef struct IndexInfo
 {
        NodeTag         type;
        int                     ii_NumIndexAttrs;
-       int                     ii_NumKeyAttrs;
        AttrNumber      ii_KeyAttrNumbers[INDEX_MAX_KEYS];
-       Node       *ii_Predicate;
-       Oid                     ii_FuncOid;
-       FmgrInfo        ii_FuncInfo;
+       List       *ii_Expressions; /* list of Expr */
+       List       *ii_ExpressionsState;        /* list of ExprState */
+       List       *ii_Predicate;       /* list of Expr */
+       List       *ii_PredicateState;          /* list of ExprState */
        bool            ii_Unique;
 } IndexInfo;
 
+/* ----------------
+ *       ExprContext_CB
+ *
+ *             List of callbacks to be called at ExprContext shutdown.
+ * ----------------
+ */
+typedef void (*ExprContextCallbackFunction) (Datum arg);
+
+typedef struct ExprContext_CB
+{
+       struct ExprContext_CB *next;
+       ExprContextCallbackFunction function;
+       Datum           arg;
+} ExprContext_CB;
+
 /* ----------------
  *       ExprContext
  *
@@ -63,14 +80,14 @@ typedef struct IndexInfo
  *             context.
  *
  *     There are two memory contexts associated with an ExprContext:
- *     * ecxt_per_query_memory is a relatively long-lived context (such as
- *       TransactionCommandContext); typically it's the same context the
- *       ExprContext node itself is allocated in.      This context can be
- *       used for purposes such as storing operator/function fcache nodes.
+ *     * ecxt_per_query_memory is a query-lifespan context, typically the same
+ *       context the ExprContext node itself is allocated in.  This context
+ *       can be used for purposes such as storing function call cache info.
  *     * ecxt_per_tuple_memory is a short-term context for expression results.
  *       As the name suggests, it will typically be reset once per tuple,
  *       before we begin to evaluate expressions for that tuple.  Each
  *       ExprContext normally has its very own per-tuple memory context.
+ *
  *     CurrentMemoryContext should be set to ecxt_per_tuple_memory before
  *     calling ExecEvalExpr() --- see ExecEvalExprSwitchContext().
  * ----------------
@@ -78,19 +95,37 @@ typedef struct IndexInfo
 typedef struct ExprContext
 {
        NodeTag         type;
+
        /* Tuples that Var nodes in expression may refer to */
        TupleTableSlot *ecxt_scantuple;
        TupleTableSlot *ecxt_innertuple;
        TupleTableSlot *ecxt_outertuple;
+
        /* Memory contexts for expression evaluation --- see notes above */
        MemoryContext ecxt_per_query_memory;
        MemoryContext ecxt_per_tuple_memory;
+
        /* Values to substitute for Param nodes in expression */
        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 */
+
+       /* Value to substitute for CaseTestExpr nodes in expression */
+       Datum           caseValue_datum;
+       bool            caseValue_isNull;
+
+       /* Value to substitute for CoerceToDomainValue nodes in expression */
+       Datum           domainValue_datum;
+       bool            domainValue_isNull;
+
+       /* Link to containing EState */
+       struct EState *ecxt_estate;
+
+       /* Functions to call back when ExprContext is shut down */
+       ExprContext_CB *ecxt_callbacks;
 } ExprContext;
 
 /*
@@ -103,45 +138,81 @@ typedef enum
        ExprEndResult                           /* there are no more elements in the set */
 } ExprDoneCond;
 
+/*
+ * 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.
+ */
+typedef enum
+{
+       SFRM_ValuePerCall = 0x01,       /* one value returned per call */
+       SFRM_Materialize = 0x02         /* result set instantiated in Tuplestore */
+} SetFunctionReturnMode;
+
 /*
  * When calling a function that might return a set (multiple rows),
  * a node of this type is passed as fcinfo->resultinfo to allow
  * return status to be passed back.  A function returning set should
  * raise an error if no such resultinfo is provided.
- *
- * XXX this mechanism is a quick hack and probably needs to be redesigned.
  */
 typedef struct ReturnSetInfo
 {
        NodeTag         type;
-       ExprDoneCond isDone;
+       /* values set by caller: */
+       ExprContext *econtext;          /* context function is being called in */
+       TupleDesc       expectedDesc;   /* tuple descriptor expected by caller */
+       int                     allowedModes;   /* bitmask: return modes caller can handle */
+       /* result status from function (but pre-initialized by caller): */
+       SetFunctionReturnMode returnMode;       /* actual return mode */
+       ExprDoneCond isDone;            /* status for ValuePerCall mode */
+       /* fields filled by function in Materialize return mode: */
+       Tuplestorestate *setResult; /* holds the complete returned tuple set */
+       TupleDesc       setDesc;                /* actual descriptor for returned tuples */
 } ReturnSetInfo;
 
-
 /* ----------------
  *             ProjectionInfo node information
  *
- *             This is all the information needed to perform projections
- *             on a tuple.  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
+ *             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.
+ *
+ *             ExecProject() evaluates the tlist, forms a tuple, and stores it
+ *             in the given slot.      Note that the result will be a "virtual" tuple
+ *             unless ExecMaterializeSlot() is then called to force it to be
+ *             converted to a physical tuple.  The slot must have a tupledesc
+ *             that matches the output of the tlist!
+ *
+ *             The planner very often produces tlists that consist entirely of
+ *             simple Var references (lower levels of a plan tree almost always
+ *             look like that).  So we have an optimization to handle that case
+ *             with minimum overhead.
  *
  *             targetlist              target list for projection
- *             len                             length of target list
- *             tupValue                array of pointers to projection results
- *             exprContext             expression context for ExecTargetList
+ *             exprContext             expression context in which to evaluate targetlist
  *             slot                    slot to place projection result in
+ *             itemIsDone              workspace for ExecProject
+ *             isVarList               TRUE if simple-Var-list optimization applies
+ *             varSlotOffsets  array indicating which slot each simple Var is from
+ *             varNumbers              array indicating attr numbers of simple Vars
+ *             lastInnerVar    highest attnum from inner tuple slot (0 if none)
+ *             lastOuterVar    highest attnum from outer tuple slot (0 if none)
+ *             lastScanVar             highest attnum from scan tuple slot (0 if none)
  * ----------------
  */
 typedef struct ProjectionInfo
 {
        NodeTag         type;
        List       *pi_targetlist;
-       int                     pi_len;
-       Datum      *pi_tupValue;
        ExprContext *pi_exprContext;
        TupleTableSlot *pi_slot;
+       ExprDoneCond *pi_itemIsDone;
+       bool            pi_isVarList;
+       int                *pi_varSlotOffsets;
+       int                *pi_varNumbers;
+       int                     pi_lastInnerVar;
+       int                     pi_lastOuterVar;
+       int                     pi_lastScanVar;
 } ProjectionInfo;
 
 /* ----------------
@@ -150,7 +221,7 @@ 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
@@ -159,53 +230,40 @@ typedef struct ProjectionInfo
  *       real output 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 correspondance between the non-junk
- *                                             attributes of the "original" tuple and the
- *                                             attributes of the "clean" tuple.
- *       junkContext:          memory context holding the JunkFilter node and all
- *                                             its subsidiary data structures.
- *
- * NOTE: the original targetList and tupType are passed to ExecInitJunkFilter
- * and do not belong to the JunkFilter.  All the other subsidiary structures
- * are created during ExecInitJunkFilter, and all of them can be freed by
- * deleting the memory context junkContext.  This would not be needed if we
- * had a cleaner approach to managing query-lifetime data structures...
+ *       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 used to hold cleaned tuple.
  * ----------------
  */
 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;
-       MemoryContext jf_junkContext;
+       TupleTableSlot *jf_resultSlot;
 } JunkFilter;
 
 /* ----------------
  *       ResultRelInfo information
  *
- *             whenever we update an existing relation, we have to
- *             update indices on the relation.  The ResultRelInfo class
- *             is used to hold all the information on result relations,
- *             including indices.. -cim 10/15/89
+ *             Whenever we update an existing relation, we have to
+ *             update indices on the relation, and perhaps also fire triggers.
+ *             The ResultRelInfo class is used to hold all the information needed
+ *             about a result relation, including indices.. -cim 10/15/89
  *
  *             RangeTableIndex                 result relation's range table index
  *             RelationDesc                    relation descriptor for result relation
  *             NumIndices                              # of indices existing on result relation
  *             IndexRelationDescs              array of relation descriptors for indices
  *             IndexRelationInfo               array of key/attr info for indices
- *             ConstraintExprs                 array of constraint-checking expressions
+ *             TrigDesc                                triggers to be fired, if any
+ *             TrigFunctions                   cached lookup info for trigger functions
+ *             TrigInstrument                  optional runtime measurements for triggers
+ *             ConstraintExprs                 array of constraint-checking expr states
  *             junkFilter                              for removing junk attributes from tuples
  * ----------------
  */
@@ -217,6 +275,9 @@ typedef struct ResultRelInfo
        int                     ri_NumIndices;
        RelationPtr ri_IndexRelationDescs;
        IndexInfo **ri_IndexRelationInfo;
+       TriggerDesc *ri_TrigDesc;
+       FmgrInfo   *ri_TrigFunctions;
+       struct Instrumentation *ri_TrigInstrument;
        List      **ri_ConstraintExprs;
        JunkFilter *ri_junkFilter;
 } ResultRelInfo;
@@ -224,156 +285,568 @@ typedef struct ResultRelInfo
 /* ----------------
  *       EState information
  *
- *             direction                                               direction of the scan
- *
- *             range_table                                             array of scan relation information
- *
- *             result_relation information             for insert/update/delete queries
- *
- *             into_relation_descriptor                relation being retrieved "into"
- *
- *             param_list_info                                 information needed to transform
- *                                                                             Param nodes into Const nodes
- *
- *             tupleTable                                              this is a pointer to an array
- *                                                                             of pointers to tuples used by
- *                                                                             the executor at any given moment.
+ * Master working state for an Executor invocation
  * ----------------
  */
 typedef struct EState
 {
        NodeTag         type;
-       ScanDirection es_direction;
-       Snapshot        es_snapshot;
-       List       *es_range_table;
+
+       /* 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 */
+
+       /* Info about target table for insert/update/delete queries: */
        ResultRelInfo *es_result_relations; /* array of ResultRelInfos */
        int                     es_num_result_relations;                /* length of array */
-       ResultRelInfo *es_result_relation_info;         /* currently active array
-                                                                                                * elt */
+       ResultRelInfo *es_result_relation_info;         /* currently active array elt */
        JunkFilter *es_junkFilter;      /* currently active junk filter */
-       Relation        es_into_relation_descriptor;
-       ParamListInfo es_param_list_info;
-       ParamExecData *es_param_exec_vals;      /* this is for subselects */
-       TupleTable      es_tupleTable;
+
+       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 */
+
+       /* Other working state: */
+       MemoryContext es_query_cxt; /* per-query context in which EState lives */
+
+       TupleTable      es_tupleTable;  /* Array of TupleTableSlots */
+
        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 */
-       MemoryContext es_query_cxt; /* per-query context in which EState lives */
+       List       *es_rowMarks;        /* not good place, but there is no other */
+       bool            es_forUpdate;   /* true = FOR UPDATE, false = FOR SHARE */
+       bool            es_rowNoWait;   /* FOR UPDATE/SHARE NOWAIT option */
+
+       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 */
 
        /*
-        * 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 */
-       struct Plan *es_origPlan;
-       Pointer         es_evalPlanQual;
-       bool       *es_evTupleNull;
-       HeapTuple  *es_evTuple;
-       bool            es_useEvalPlan;
+       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? */
 } EState;
 
-/* ----------------
- *             Executor Type information needed by plannodes.h
- *
- *|            Note: the bogus classes CommonState and CommonScanState exist only
- *|                      because our inheritance system only allows single inheritance
- *|                      and we have to have unique slot names.  Hence two or more
- *|                      classes which want to have a common slot must ALL inherit
- *|                      the slot from some other class.  (This is a big hack to
- *|                      allow our classes to share slot names..)
- *|
- *|            Example:
- *|                      the class Result and the class NestLoop nodes both want
- *|                      a slot called "OuterTuple" so they both have to inherit
- *|                      it from some other class.  In this case they inherit
- *|                      it from CommonState.  "CommonState" and "CommonScanState" are
- *|                      the best names I could come up with for this sort of
- *|                      stuff.
- *|
- *|                      As a result, many classes have extra slots which they
- *|                      don't use.  These slots are denoted (unused) in the
- *|                      comment preceeding the class definition.      If you
- *|                      comes up with a better idea of a way of doing things
- *|                      along these lines, then feel free to make your idea
- *|                      known to me.. -cim 10/15/89
- * ----------------
+
+/* ----------------------------------------------------------------
+ *                              Tuple Hash Tables
+ *
+ * All-in-memory tuple hash tables are used for a number of purposes.
+ * ----------------------------------------------------------------
  */
+typedef struct TupleHashEntryData *TupleHashEntry;
+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 */
+       /* there may be additional data beyond the end of this struct */
+} TupleHashEntryData;                  /* VARIABLE LENGTH STRUCT */
+
+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 */
+       MemoryContext tablecxt;         /* memory context containing table */
+       MemoryContext tempcxt;          /* context for function evaluations */
+       Size            entrysize;              /* actual size to make each hash entry */
+       TupleTableSlot *tableslot;      /* slot for referencing table entries */
+       TupleTableSlot *inputslot;      /* current input tuple's slot */
+} TupleHashTableData;
+
+typedef HASH_SEQ_STATUS TupleHashIterator;
+
+#define ResetTupleHashIterator(htable, iter) \
+       hash_seq_init(iter, (htable)->hashtab)
+#define ScanTupleHashTable(iter) \
+       ((TupleHashEntry) hash_seq_search(iter))
+
 
 /* ----------------------------------------------------------------
- *                              Common Executor State Information
+ *                              Expression State Trees
+ *
+ * Each executable expression tree has a parallel ExprState tree.
+ *
+ * Unlike PlanState, there is not an exact one-for-one correspondence between
+ * ExprState node types and Expr node types.  Many Expr node types have no
+ * need for node-type-specific run-time state, and so they can use plain
+ * ExprState or GenericExprState as their associated ExprState node type.
  * ----------------------------------------------------------------
  */
 
 /* ----------------
- *      CommonState information
+ *             ExprState node
+ *
+ * ExprState is the common superclass for all ExprState-type nodes.
+ *
+ * It can also be instantiated directly for leaf Expr nodes that need no
+ * local run-time state (such as Var, Const, or Param).
+ *
+ * To save on dispatch overhead, each ExprState node contains a function
+ * pointer to the routine to execute to evaluate the node.
+ * ----------------
+ */
+
+typedef struct ExprState ExprState;
+
+typedef Datum (*ExprStateEvalFunc) (ExprState *expression,
+                                                                                               ExprContext *econtext,
+                                                                                               bool *isNull,
+                                                                                               ExprDoneCond *isDone);
+
+struct ExprState
+{
+       NodeTag         type;
+       Expr       *expr;                       /* associated Expr node */
+       ExprStateEvalFunc evalfunc; /* routine to run to execute node */
+};
+
+/* ----------------
+ *             GenericExprState node
+ *
+ * This is used for Expr node types that need no local run-time state,
+ * but have one child Expr node.
+ * ----------------
+ */
+typedef struct GenericExprState
+{
+       ExprState       xprstate;
+       ExprState  *arg;                        /* state of my child node */
+} GenericExprState;
+
+/* ----------------
+ *             AggrefExprState node
+ * ----------------
+ */
+typedef struct AggrefExprState
+{
+       ExprState       xprstate;
+       ExprState  *target;                     /* state of my child node */
+       int                     aggno;                  /* ID number for agg within its plan node */
+} AggrefExprState;
+
+/* ----------------
+ *             ArrayRefExprState node
+ *
+ * Note: array types can be fixed-length (typlen > 0), but only when the
+ * element type is itself fixed-length.  Otherwise they are varlena structures
+ * and have typlen = -1.  In any case, an array type is never pass-by-value.
+ * ----------------
+ */
+typedef struct ArrayRefExprState
+{
+       ExprState       xprstate;
+       List       *refupperindexpr;    /* states for child nodes */
+       List       *reflowerindexpr;
+       ExprState  *refexpr;
+       ExprState  *refassgnexpr;
+       int16           refattrlength;  /* typlen of array type */
+       int16           refelemlength;  /* typlen of the array element type */
+       bool            refelembyval;   /* is the element type pass-by-value? */
+       char            refelemalign;   /* typalign of the element type */
+} ArrayRefExprState;
+
+/* ----------------
+ *             FuncExprState node
  *
- *             Superclass for all executor node-state object types.
+ * Although named for FuncExpr, this is also used for OpExpr, DistinctExpr,
+ * and NullIf nodes; be careful to check what xprstate.expr is actually
+ * pointing at!
+ * ----------------
+ */
+typedef struct FuncExprState
+{
+       ExprState       xprstate;
+       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.
+        */
+       FmgrInfo        func;
+
+       /*
+        * We also need to store argument values across calls when evaluating a
+        * function-returning-set.
+        *
+        * 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
+        * argument values to the function again (and again, until it returns
+        * ExprEndResult).
+        */
+       bool            setArgsValid;
+
+       /*
+        * 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.
+        */
+       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).
+        */
+       bool            shutdown_reg;   /* a shutdown callback is registered */
+
+       /*
+        * Current argument data for a set-valued function; contains valid data
+        * only if setArgsValid is true.
+        */
+       FunctionCallInfoData setArgs;
+} FuncExprState;
+
+/* ----------------
+ *             ScalarArrayOpExprState node
+ *
+ * This is a FuncExprState plus some additional data.
+ * ----------------
+ */
+typedef struct ScalarArrayOpExprState
+{
+       FuncExprState fxprstate;
+       /* Cached info about array element type */
+       Oid                     element_type;
+       int16           typlen;
+       bool            typbyval;
+       char            typalign;
+} ScalarArrayOpExprState;
+
+/* ----------------
+ *             BoolExprState node
+ * ----------------
+ */
+typedef struct BoolExprState
+{
+       ExprState       xprstate;
+       List       *args;                       /* states of argument expression(s) */
+} BoolExprState;
+
+/* ----------------
+ *             SubPlanState node
+ * ----------------
+ */
+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) */
+       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 */
+       ProjectionInfo *projRight;      /* for projecting subselect output */
+       TupleHashTable hashtable;       /* hash table for no-nulls subselect rows */
+       TupleHashTable hashnulls;       /* hash table for rows with null(s) */
+       bool            havehashrows;   /* TRUE if hashtable is not empty */
+       bool            havenullrows;   /* TRUE if hashnulls is not empty */
+       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 */
+} SubPlanState;
+
+/* ----------------
+ *             FieldSelectState node
+ * ----------------
+ */
+typedef struct FieldSelectState
+{
+       ExprState       xprstate;
+       ExprState  *arg;                        /* input expression */
+       TupleDesc       argdesc;                /* tupdesc for most recent input */
+} FieldSelectState;
+
+/* ----------------
+ *             FieldStoreState node
+ * ----------------
+ */
+typedef struct FieldStoreState
+{
+       ExprState       xprstate;
+       ExprState  *arg;                        /* input tuple value */
+       List       *newvals;            /* new value(s) for field(s) */
+       TupleDesc       argdesc;                /* tupdesc for most recent input */
+} FieldStoreState;
+
+/* ----------------
+ *             ConvertRowtypeExprState node
+ * ----------------
+ */
+typedef struct ConvertRowtypeExprState
+{
+       ExprState       xprstate;
+       ExprState  *arg;                        /* input tuple value */
+       TupleDesc       indesc;                 /* tupdesc for source rowtype */
+       TupleDesc       outdesc;                /* tupdesc for result rowtype */
+       AttrNumber *attrMap;            /* indexes of input fields, or 0 for null */
+       Datum      *invalues;           /* workspace for deconstructing source */
+       bool       *inisnull;
+       Datum      *outvalues;          /* workspace for constructing result */
+       bool       *outisnull;
+} ConvertRowtypeExprState;
+
+/* ----------------
+ *             CaseExprState node
+ * ----------------
+ */
+typedef struct CaseExprState
+{
+       ExprState       xprstate;
+       ExprState  *arg;                        /* implicit equality comparison argument */
+       List       *args;                       /* the arguments (list of WHEN clauses) */
+       ExprState  *defresult;          /* the default result (ELSE clause) */
+} CaseExprState;
+
+/* ----------------
+ *             CaseWhenState node
+ * ----------------
+ */
+typedef struct CaseWhenState
+{
+       ExprState       xprstate;
+       ExprState  *expr;                       /* condition expression */
+       ExprState  *result;                     /* substitution result */
+} CaseWhenState;
+
+/* ----------------
+ *             ArrayExprState node
  *
- *             OuterTupleSlot     pointer to slot containing current "outer" tuple
- *             ResultTupleSlot    pointer to slot in tuple table for projected tuple
- *             ExprContext                node's expression-evaluation context
- *             ProjInfo                   info this node uses to form tuple projections
- *             TupFromTlist       state flag used by some node types (why kept here?)
+ * Note: ARRAY[] expressions always produce varlena arrays, never fixed-length
+ * arrays.
  * ----------------
  */
-typedef struct CommonState
+typedef struct ArrayExprState
 {
-       NodeTag         type;                   /* its first field is NodeTag */
-       TupleTableSlot *cs_OuterTupleSlot;
-       TupleTableSlot *cs_ResultTupleSlot;
-       ExprContext *cs_ExprContext;
-       ProjectionInfo *cs_ProjInfo;
-       bool            cs_TupFromTlist;
-} CommonState;
+       ExprState       xprstate;
+       List       *elements;           /* states for child nodes */
+       int16           elemlength;             /* typlen of the array element type */
+       bool            elembyval;              /* is the element type pass-by-value? */
+       char            elemalign;              /* typalign of the element type */
+} ArrayExprState;
+
+/* ----------------
+ *             RowExprState node
+ * ----------------
+ */
+typedef struct RowExprState
+{
+       ExprState       xprstate;
+       List       *args;                       /* the arguments */
+       TupleDesc       tupdesc;                /* descriptor for result tuples */
+} RowExprState;
+
+/* ----------------
+ *             CoalesceExprState node
+ * ----------------
+ */
+typedef struct CoalesceExprState
+{
+       ExprState       xprstate;
+       List       *args;                       /* the arguments */
+} CoalesceExprState;
+
+/* ----------------
+ *             MinMaxExprState node
+ * ----------------
+ */
+typedef struct MinMaxExprState
+{
+       ExprState       xprstate;
+       List       *args;                       /* the arguments */
+       FmgrInfo        cfunc;                  /* lookup info for comparison func */
+} MinMaxExprState;
+
+/* ----------------
+ *             CoerceToDomainState node
+ * ----------------
+ */
+typedef struct CoerceToDomainState
+{
+       ExprState       xprstate;
+       ExprState  *arg;                        /* input expression */
+       /* Cached list of constraints that need to be checked */
+       List       *constraints;        /* list of DomainConstraintState nodes */
+} CoerceToDomainState;
+
+/*
+ * DomainConstraintState - one item to check during CoerceToDomain
+ *
+ * Note: this is just a Node, and not an ExprState, because it has no
+ * corresponding Expr to link to.  Nonetheless it is part of an ExprState
+ * tree, so we give it a name following the xxxState convention.
+ */
+typedef enum DomainConstraintType
+{
+       DOM_CONSTRAINT_NOTNULL,
+       DOM_CONSTRAINT_CHECK
+} DomainConstraintType;
+
+typedef struct DomainConstraintState
+{
+       NodeTag         type;
+       DomainConstraintType constrainttype;            /* constraint type */
+       char       *name;                       /* name of constraint (for error msgs) */
+       ExprState  *check_expr;         /* for CHECK, a boolean expression */
+} DomainConstraintState;
 
 
 /* ----------------------------------------------------------------
- *                              Control Node State Information
+ *                              Executor State Trees
+ *
+ * An executing query has a PlanState tree paralleling the Plan tree
+ * that describes the plan.
  * ----------------------------------------------------------------
  */
 
 /* ----------------
- *      ResultState information
+ *             PlanState node
  *
- *             done                       flag which tells us to quit when we
- *                                                have already returned a constant tuple.
+ * We never actually instantiate any PlanState nodes; this is just the common
+ * abstract superclass for all PlanState-type nodes.
+ * ----------------
+ */
+typedef struct PlanState
+{
+       NodeTag         type;
+
+       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 */
+
+       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).
+        */
+       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       *subPlan;            /* SubPlanState nodes in my expressions */
+
+       /*
+        * State for management of parameter-change-driven rescanning
+        */
+       Bitmapset  *chgParam;           /* set of IDs of changed Params */
+
+       /*
+        * 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 */
+} PlanState;
+
+/* ----------------
+ *     these are are defined to avoid confusion problems with "left"
+ *     and "right" and "inner" and "outer".  The convention is that
+ *     the "left" plan is the "outer" plan and the "right" plan is
+ *     the inner plan, but these make the code more readable.
+ * ----------------
+ */
+#define innerPlanState(node)           (((PlanState *)(node))->righttree)
+#define outerPlanState(node)           (((PlanState *)(node))->lefttree)
+
+
+/* ----------------
+ *      ResultState information
  * ----------------
  */
 typedef struct ResultState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
-       bool            rs_done;
-       bool            rs_checkqual;
+       PlanState       ps;                             /* its first field is NodeTag */
+       ExprState  *resconstantqual;
+       bool            rs_done;                /* are we done? */
+       bool            rs_checkqual;   /* do we need to check the qual? */
 } ResultState;
 
 /* ----------------
  *      AppendState information
  *
- *             whichplan               which plan is being executed (0 .. n-1)
  *             nplans                  how many plans are in the list
- *             initialized             array of ExecInitNode() results
+ *             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
 {
-       CommonState cstate;                     /* its first field is NodeTag */
-       int                     as_whichplan;
+       PlanState       ps;                             /* its first field is NodeTag */
+       PlanState **appendplans;        /* array of PlanStates for my inputs */
        int                     as_nplans;
-       bool       *as_initialized;
+       int                     as_whichplan;
+       int                     as_firstplan;
+       int                     as_lastplan;
 } AppendState;
 
+/* ----------------
+ *      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
  * ----------------------------------------------------------------
  */
 
 /* ----------------
- *      CommonScanState information
+ *      ScanState information
  *
- *             CommonScanState extends CommonState for node types that represent
+ *             ScanState extends PlanState for node types that represent
  *             scans of an underlying relation.  It can also be used for nodes
  *             that scan the output of an underlying plan node --- in that case,
  *             only ScanTupleSlot is actually useful, and it refers to the tuple
@@ -384,73 +857,133 @@ typedef struct AppendState
  *             ScanTupleSlot      pointer to slot in tuple table holding scan tuple
  * ----------------
  */
-typedef struct CommonScanState
+typedef struct ScanState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
-       Relation        css_currentRelation;
-       HeapScanDesc css_currentScanDesc;
-       TupleTableSlot *css_ScanTupleSlot;
-} CommonScanState;
+       PlanState       ps;                             /* its first field is NodeTag */
+       Relation        ss_currentRelation;
+       HeapScanDesc ss_currentScanDesc;
+       TupleTableSlot *ss_ScanTupleSlot;
+} ScanState;
 
 /*
- * SeqScan uses a bare CommonScanState as its state item, since it needs
+ * SeqScan uses a bare ScanState as its state node, since it needs
  * no additional fields.
  */
+typedef ScanState SeqScanState;
+
+/*
+ * These structs store information about index quals that don't have simple
+ * constant right-hand sides.  See comments for ExecIndexBuildScanKeys()
+ * for discussion.
+ */
+typedef struct
+{
+       ScanKey         scan_key;               /* scankey to put value into */
+       ExprState  *key_expr;           /* expr to evaluate to get value */
+} IndexRuntimeKeyInfo;
+
+typedef struct
+{
+       ScanKey         scan_key;               /* scankey to put value into */
+       ExprState  *array_expr;         /* expr to evaluate to get array value */
+       int                     next_elem;              /* next array element to use */
+       int                     num_elems;              /* number of elems in current array value */
+       Datum      *elem_values;        /* array of num_elems Datums */
+       bool       *elem_nulls;         /* array of num_elems is-null flags */
+} IndexArrayKeyInfo;
 
 /* ----------------
  *      IndexScanState information
  *
- *             Note that an IndexScan node *also* has a CommonScanState state item.
- *             IndexScanState stores the info needed specifically for indexing.
- *             There's probably no good reason why this is a separate node type
- *             rather than an extension of CommonScanState.
- *
- *             NumIndices                 number of indices in this scan
- *             IndexPtr                   current index in use
- *             ScanKeys                   Skey structures to scan index rels
- *             NumScanKeys                array of no of keys in each Skey struct
- *             RuntimeKeyInfo     array of array of flags for Skeys evaled 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
+ *             RuntimeContext     expr context for evaling runtime Skeys
+ *             RelationDesc       index relation descriptor
+ *             ScanDesc                   index scan descriptor
  * ----------------
  */
 typedef struct IndexScanState
 {
-       NodeTag         type;
-       int                     iss_NumIndices;
-       int                     iss_IndexPtr;
-       int                     iss_MarkIndexPtr;
-       ScanKey    *iss_ScanKeys;
-       int                *iss_NumScanKeys;
-       int               **iss_RuntimeKeyInfo;
-       ExprContext *iss_RuntimeContext;
+       ScanState       ss;                             /* its first field is NodeTag */
+       List       *indexqualorig;
+       ScanKey         iss_ScanKeys;
+       int                     iss_NumScanKeys;
+       IndexRuntimeKeyInfo *iss_RuntimeKeys;
+       int                     iss_NumRuntimeKeys;
        bool            iss_RuntimeKeysReady;
-       RelationPtr iss_RelationDescs;
-       IndexScanDescPtr iss_ScanDescs;
-       HeapTupleData iss_htup;
+       ExprContext *iss_RuntimeContext;
+       Relation        iss_RelationDesc;
+       IndexScanDesc iss_ScanDesc;
 } IndexScanState;
 
 /* ----------------
- *      TidScanState information
+ *      BitmapIndexScanState information
  *
- *             Note that a TidScan node *also* has a CommonScanState state item.
- *             There's probably no good reason why this is a separate node type
- *             rather than an extension of CommonScanState.
+ *             result                     bitmap to return output into, or NULL
+ *             ScanKeys                   Skey structures to scan index rel
+ *             NumScanKeys                number of Skey structs
+ *             RuntimeKeys                info about Skeys that must be evaluated at runtime
+ *             NumRuntimeKeys     number of RuntimeKeys structs
+ *             ArrayKeys                  info about Skeys that come from ScalarArrayOpExprs
+ *             NumArrayKeys       number of ArrayKeys structs
+ *             RuntimeKeysReady   true if runtime Skeys have been computed
+ *             RuntimeContext     expr context for evaling runtime Skeys
+ *             RelationDesc       index relation descriptor
+ *             ScanDesc                   index scan descriptor
+ * ----------------
+ */
+typedef struct BitmapIndexScanState
+{
+       ScanState       ss;                             /* its first field is NodeTag */
+       TIDBitmap  *biss_result;
+       ScanKey         biss_ScanKeys;
+       int                     biss_NumScanKeys;
+       IndexRuntimeKeyInfo *biss_RuntimeKeys;
+       int                     biss_NumRuntimeKeys;
+       IndexArrayKeyInfo *biss_ArrayKeys;
+       int                     biss_NumArrayKeys;
+       bool            biss_RuntimeKeysReady;
+       ExprContext *biss_RuntimeContext;
+       Relation        biss_RelationDesc;
+       IndexScanDesc biss_ScanDesc;
+} BitmapIndexScanState;
+
+/* ----------------
+ *      BitmapHeapScanState information
+ *
+ *             bitmapqualorig     execution state for bitmapqualorig expressions
+ *             tbm                                bitmap obtained from child index scan(s)
+ *             tbmres                     current-page data
+ * ----------------
+ */
+typedef struct BitmapHeapScanState
+{
+       ScanState       ss;                             /* its first field is NodeTag */
+       List       *bitmapqualorig;
+       TIDBitmap  *tbm;
+       TBMIterateResult *tbmres;
+} BitmapHeapScanState;
+
+/* ----------------
+ *      TidScanState information
  *
  *             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
 {
-       NodeTag         type;
+       ScanState       ss;                             /* its first field is NodeTag */
+       List       *tss_tidquals;       /* list of ExprState nodes */
        int                     tss_NumTids;
        int                     tss_TidPtr;
        int                     tss_MarkTidPtr;
-       ItemPointer *tss_TidList;
+       ItemPointerData *tss_TidList;
        HeapTupleData tss_htup;
 } TidScanState;
 
@@ -466,10 +999,30 @@ typedef struct TidScanState
  */
 typedef struct SubqueryScanState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
+       ScanState       ss;                             /* its first field is NodeTag */
+       PlanState  *subplan;
        EState     *sss_SubEState;
 } SubqueryScanState;
 
+/* ----------------
+ *      FunctionScanState information
+ *
+ *             Function nodes are used to scan the results of a
+ *             function appearing in FROM (typically a function returning set).
+ *
+ *             tupdesc                         expected return tuple description
+ *             tuplestorestate         private state of tuplestore.c
+ *             funcexpr                        state for function expression being evaluated
+ * ----------------
+ */
+typedef struct FunctionScanState
+{
+       ScanState       ss;                             /* its first field is NodeTag */
+       TupleDesc       tupdesc;
+       Tuplestorestate *tuplestorestate;
+       ExprState  *funcexpr;
+} FunctionScanState;
+
 /* ----------------------------------------------------------------
  *                              Join State Information
  * ----------------------------------------------------------------
@@ -478,11 +1031,15 @@ typedef struct SubqueryScanState
 /* ----------------
  *      JoinState information
  *
- *             Superclass for state items of join nodes.
- *             Currently this is the same as CommonState.
+ *             Superclass for state nodes of join plans.
  * ----------------
  */
-typedef CommonState JoinState;
+typedef struct JoinState
+{
+       PlanState       ps;
+       JoinType        jointype;
+       List       *joinqual;           /* JOIN quals (in addition to ps.qual) */
+} JoinState;
 
 /* ----------------
  *      NestLoopState information
@@ -494,7 +1051,7 @@ typedef CommonState JoinState;
  */
 typedef struct NestLoopState
 {
-       JoinState       jstate;                 /* its first field is NodeTag */
+       JoinState       js;                             /* its first field is NodeTag */
        bool            nl_NeedNewOuter;
        bool            nl_MatchedOuter;
        TupleTableSlot *nl_NullInnerTupleSlot;
@@ -503,24 +1060,33 @@ 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
+ *             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       jstate;                 /* its first field is NodeTag */
-       List       *mj_OuterSkipQual;
-       List       *mj_InnerSkipQual;
+       JoinState       js;                             /* its first field is NodeTag */
+       int                     mj_NumClauses;
+       MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */
        int                     mj_JoinState;
+       bool            mj_FillOuter;
+       bool            mj_FillInner;
        bool            mj_MatchedOuter;
        bool            mj_MatchedInner;
        TupleTableSlot *mj_OuterTupleSlot;
@@ -528,39 +1094,54 @@ 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
+ *                                                             (NULL if table not built yet)
+ *             hj_CurHashValue                 hash value for current outer tuple
  *             hj_CurBucketNo                  bucket# for current outer tuple
  *             hj_CurTuple                             last inner tuple matched to current outer
  *                                                             tuple, or NULL if starting search
- *                                                             (CurBucketNo and CurTuple are meaningless
- *                                                              unless OuterTupleSlot is nonempty!)
- *             hj_InnerHashKey                 the inner hash key in the hashjoin condition
+ *                                                             (CurHashValue, CurBucketNo and CurTuple are
+ *                                                              undefined if OuterTupleSlot is empty!)
+ *             hj_OuterHashKeys                the outer hash keys in the hashjoin condition
+ *             hj_InnerHashKeys                the inner hash keys in the hashjoin condition
+ *             hj_HashOperators                the join operators in the hashjoin condition
  *             hj_OuterTupleSlot               tuple slot for outer tuples
  *             hj_HashTupleSlot                tuple slot for hashed tuples
  *             hj_NullInnerTupleSlot   prepared null tuple for left outer joins
+ *             hj_FirstOuterTupleSlot  first tuple retrieved from outer plan
  *             hj_NeedNewOuter                 true if need new outer tuple on next call
  *             hj_MatchedOuter                 true if found a join match for current outer
- *             hj_hashdone                             true if hash-table-build phase is done
  * ----------------
  */
+
+/* these structs are defined in executor/hashjoin.h: */
+typedef struct HashJoinTupleData *HashJoinTuple;
+typedef struct HashJoinTableData *HashJoinTable;
+
 typedef struct HashJoinState
 {
-       JoinState       jstate;                 /* its first field is NodeTag */
+       JoinState       js;                             /* its first field is NodeTag */
+       List       *hashclauses;        /* list of ExprState nodes */
        HashJoinTable hj_HashTable;
+       uint32          hj_CurHashValue;
        int                     hj_CurBucketNo;
        HashJoinTuple hj_CurTuple;
-       Node       *hj_InnerHashKey;
+       List       *hj_OuterHashKeys;           /* list of ExprState nodes */
+       List       *hj_InnerHashKeys;           /* list of ExprState nodes */
+       List       *hj_HashOperators;           /* list of operator OIDs */
        TupleTableSlot *hj_OuterTupleSlot;
        TupleTableSlot *hj_HashTupleSlot;
        TupleTableSlot *hj_NullInnerTupleSlot;
+       TupleTableSlot *hj_FirstOuterTupleSlot;
        bool            hj_NeedNewOuter;
        bool            hj_MatchedOuter;
-       bool            hj_hashdone;
 } HashJoinState;
 
 
@@ -575,41 +1156,26 @@ typedef struct HashJoinState
  *             materialize nodes are used to materialize the results
  *             of a subplan into a temporary file.
  *
- *             csstate.css_ScanTupleSlot refers to output of underlying plan.
- *
- *             tuplestorestate         private state of tuplestore.c
+ *             ss.ss_ScanTupleSlot refers to output of underlying plan.
  * ----------------
  */
 typedef struct MaterialState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
-       void       *tuplestorestate;
+       ScanState       ss;                             /* its first field is NodeTag */
+       void       *tuplestorestate;    /* private state of tuplestore.c */
+       bool            eof_underlying; /* reached end of underlying plan? */
 } MaterialState;
 
-/* ---------------------
- *     AggregateState information
- *
- *     csstate.css_ScanTupleSlot refers to output of underlying plan.
- *
- *     Note: the associated ExprContext contains ecxt_aggvalues and ecxt_aggnulls
- *     arrays, which hold the computed agg values for the current input group
- *     during evaluation of an Agg node's output tuple(s).
- * -------------------------
+/* ----------------
+ *      SortState information
+ * ----------------
  */
-typedef struct AggStatePerAggData *AggStatePerAgg;             /* private in nodeAgg.c */
-
-typedef struct AggState
+typedef struct SortState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
-       List       *aggs;                       /* all Aggref nodes in targetlist & quals */
-       int                     numaggs;                /* length of list (could be zero!) */
-       AggStatePerAgg peragg;          /* per-Aggref working state */
-       MemoryContext tup_cxt;          /* context for per-output-tuple
-                                                                * expressions */
-       MemoryContext agg_cxt[2];       /* pair of expression eval memory contexts */
-       int                     which_cxt;              /* 0 or 1, indicates current agg_cxt */
-       bool            agg_done;               /* indicates completion of Agg scan */
-} AggState;
+       ScanState       ss;                             /* its first field is NodeTag */
+       bool            sort_Done;              /* sort completed yet? */
+       void       *tuplesortstate; /* private state of tuplesort.c */
+} SortState;
 
 /* ---------------------
  *     GroupState information
@@ -617,26 +1183,46 @@ typedef struct AggState
  */
 typedef struct GroupState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
+       ScanState       ss;                             /* its first field is NodeTag */
        FmgrInfo   *eqfunctions;        /* per-field lookup data for equality fns */
-       bool            grp_useFirstTuple;              /* first tuple not processed yet */
-       bool            grp_done;
-       HeapTuple       grp_firstTuple;
+       bool            grp_done;               /* indicates completion of Group scan */
 } GroupState;
 
-/* ----------------
- *      SortState information
+/* ---------------------
+ *     AggState information
  *
- *             sort_Done               indicates whether sort has been performed yet
- *             tuplesortstate  private state of tuplesort.c
- * ----------------
+ *     ss.ss_ScanTupleSlot refers to output of underlying plan.
+ *
+ *     Note: ss.ps.ps_ExprContext contains ecxt_aggvalues and
+ *     ecxt_aggnulls arrays, which hold the computed agg values for the current
+ *     input group during evaluation of an Agg node's output tuple(s).  We
+ *     create a second ExprContext, tmpcontext, in which to evaluate input
+ *     expressions and run the aggregate transition functions.
+ * -------------------------
  */
-typedef struct SortState
+/* these structs are private in nodeAgg.c: */
+typedef struct AggStatePerAggData *AggStatePerAgg;
+typedef struct AggStatePerGroupData *AggStatePerGroup;
+
+typedef struct AggState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
-       bool            sort_Done;
-       void       *tuplesortstate;
-} SortState;
+       ScanState       ss;                             /* its first field is NodeTag */
+       List       *aggs;                       /* all Aggref nodes in targetlist & quals */
+       int                     numaggs;                /* length of list (could be zero!) */
+       FmgrInfo   *eqfunctions;        /* per-grouping-field equality fns */
+       FmgrInfo   *hashfunctions;      /* per-grouping-field hash fns */
+       AggStatePerAgg peragg;          /* per-Aggref information */
+       MemoryContext aggcontext;       /* memory context for long-lived data */
+       ExprContext *tmpcontext;        /* econtext for input expressions */
+       bool            agg_done;               /* indicates completion of Agg scan */
+       /* these fields are used in AGG_PLAIN and AGG_SORTED modes: */
+       AggStatePerGroup pergroup;      /* per-Aggref-per-group working state */
+       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 */
+       bool            table_filled;   /* hash table filled yet? */
+       TupleHashIterator hashiter; /* for iterating through hash table */
+} AggState;
 
 /* ----------------
  *      UniqueState information
@@ -644,19 +1230,30 @@ typedef struct SortState
  *             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.
  * ----------------
  */
 typedef struct UniqueState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
+       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;
 
+/* ----------------
+ *      HashState information
+ * ----------------
+ */
+typedef struct HashState
+{
+       PlanState       ps;                             /* its first field is NodeTag */
+       HashJoinTable hashtable;        /* hash table for the hashjoin */
+       List       *hashkeys;           /* list of ExprState nodes */
+       /* hashkeys is same as parent's hj_InnerHashKeys */
+} HashState;
+
 /* ----------------
  *      SetOpState information
  *
@@ -668,7 +1265,7 @@ typedef struct UniqueState
  */
 typedef struct SetOpState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
+       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 */
@@ -686,60 +1283,30 @@ typedef struct SetOpState
  * offset is the number of initial tuples to skip (0 does nothing).
  * count is the number of tuples to return after skipping the offset tuples.
  * If no limit count was specified, count is undefined and noCount is true.
+ * When lstate == LIMIT_INITIAL, offset/count/noCount haven't been set yet.
  * ----------------
  */
+typedef enum
+{
+       LIMIT_INITIAL,                          /* initial state for LIMIT node */
+       LIMIT_EMPTY,                            /* there are no returnable rows */
+       LIMIT_INWINDOW,                         /* have returned a row in the window */
+       LIMIT_SUBPLANEOF,                       /* at EOF of subplan (within window) */
+       LIMIT_WINDOWEND,                        /* stepped off end of window */
+       LIMIT_WINDOWSTART                       /* stepped off beginning of window */
+} LimitStateCond;
+
 typedef struct LimitState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
+       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 */
-       long            position;               /* 1-based index of last tuple fetched */
-       bool            parmsSet;               /* have we calculated offset/limit yet? */
        bool            noCount;                /* if true, ignore count */
-       bool            atEnd;                  /* if true, we've reached EOF of subplan */
+       LimitStateCond lstate;          /* state machine status, as above */
+       long            position;               /* 1-based index of last tuple returned */
+       TupleTableSlot *subSlot;        /* tuple last obtained from subplan */
 } LimitState;
 
-
-/* ----------------
- *      HashState information
- *
- *             hashtable                       hash table for the hashjoin
- * ----------------
- */
-typedef struct HashState
-{
-       CommonState cstate;                     /* its first field is NodeTag */
-       HashJoinTable hashtable;
-} HashState;
-
-#ifdef NOT_USED
-/* -----------------------
- *     TeeState information
- *       leftPlace  :    next item in the queue unseen by the left parent
- *       rightPlace :    next item in the queue unseen by the right parent
- *       lastPlace  :    last item in the queue
- *       bufferRelname :  name of the relation used as the buffer queue
- *       bufferRel             :  the relation used as the buffer queue
- *       mcxt                  :  for now, tee's have their own memory context
- *                                        may be cleaned up later if portals are cleaned up
- *
- * initially, a Tee starts with [left/right]Place variables set to     -1.
- * on cleanup, queue is free'd when both leftPlace and rightPlace = -1
- * -------------------------
-*/
-typedef struct TeeState
-{
-       CommonState cstate;                     /* its first field is NodeTag */
-       int                     tee_leftPlace,
-                               tee_rightPlace,
-                               tee_lastPlace;
-       char       *tee_bufferRelname;
-       Relation        tee_bufferRel;
-       MemoryContext tee_mcxt;
-       HeapScanDesc tee_leftScanDesc,
-                               tee_rightScanDesc;
-}                      TeeState;
-
-#endif
-
-#endif  /* EXECNODES_H */
+#endif   /* EXECNODES_H */