OSDN Git Service

Phase 1 of read-only-plans project: cause executor state nodes to point
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Dec 2002 15:50:39 +0000 (15:50 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Dec 2002 15:50:39 +0000 (15:50 +0000)
to plan nodes, not vice-versa.  All executor state nodes now inherit from
struct PlanState.  Copying of plan trees has been simplified by not
storing a list of SubPlans in Plan nodes (eliminating duplicate links).
The executor still needs such a list, but it can build it during
ExecutorStart since it has to scan the plan tree anyway.
No initdb forced since no stored-on-disk structures changed, but you
will need a full recompile because of node-numbering changes.

71 files changed:
src/backend/commands/explain.c
src/backend/commands/portalcmds.c
src/backend/commands/prepare.c
src/backend/executor/README
src/backend/executor/execAmi.c
src/backend/executor/execMain.c
src/backend/executor/execProcnode.c
src/backend/executor/execQual.c
src/backend/executor/execScan.c
src/backend/executor/execTuples.c
src/backend/executor/execUtils.c
src/backend/executor/functions.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeAppend.c
src/backend/executor/nodeFunctionscan.c
src/backend/executor/nodeGroup.c
src/backend/executor/nodeHash.c
src/backend/executor/nodeHashjoin.c
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeLimit.c
src/backend/executor/nodeMaterial.c
src/backend/executor/nodeMergejoin.c
src/backend/executor/nodeNestloop.c
src/backend/executor/nodeResult.c
src/backend/executor/nodeSeqscan.c
src/backend/executor/nodeSetOp.c
src/backend/executor/nodeSort.c
src/backend/executor/nodeSubplan.c
src/backend/executor/nodeSubqueryscan.c
src/backend/executor/nodeTidscan.c
src/backend/executor/nodeUnique.c
src/backend/executor/spi.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/util/pathnode.c
src/backend/tcop/pquery.c
src/backend/utils/mmgr/portalmem.c
src/include/executor/execdesc.h
src/include/executor/executor.h
src/include/executor/nodeAgg.h
src/include/executor/nodeAppend.h
src/include/executor/nodeFunctionscan.h
src/include/executor/nodeGroup.h
src/include/executor/nodeHash.h
src/include/executor/nodeHashjoin.h
src/include/executor/nodeIndexscan.h
src/include/executor/nodeLimit.h
src/include/executor/nodeMaterial.h
src/include/executor/nodeMergejoin.h
src/include/executor/nodeNestloop.h
src/include/executor/nodeResult.h
src/include/executor/nodeSeqscan.h
src/include/executor/nodeSetOp.h
src/include/executor/nodeSort.h
src/include/executor/nodeSubplan.h
src/include/executor/nodeSubqueryscan.h
src/include/executor/nodeTidscan.h
src/include/executor/nodeUnique.h
src/include/nodes/execnodes.h
src/include/nodes/nodes.h
src/include/nodes/params.h
src/include/nodes/plannodes.h
src/include/nodes/print.h
src/include/nodes/relation.h
src/include/tcop/pquery.h
src/include/utils/portal.h
src/pl/plpgsql/src/pl_exec.c

index 0e6ca88..e2d1a6e 100644 (file)
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.93 2002/11/13 00:39:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.94 2002/12/05 15:50:30 tgl Exp $
  *
  */
 
@@ -34,17 +34,19 @@ typedef struct ExplainState
 {
        /* options */
        bool            printCost;              /* print cost */
-       bool            printNodes;             /* do nodeToString() instead */
-       bool            printAnalyze;           /* print actual times */
+       bool            printNodes;             /* do nodeToString() too */
+       bool            printAnalyze;   /* print actual times */
        /* other states */
        List       *rtable;                     /* range table */
 } ExplainState;
 
-static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es);
 static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
                                TupOutputState *tstate);
-static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
-                               int indent, ExplainState *es);
+static double elapsed_time(struct timeval *starttime);
+static void explain_outNode(StringInfo str,
+                                                       Plan *plan, PlanState *planstate,
+                                                       Plan *outer_plan,
+                                                       int indent, ExplainState *es);
 static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel,
                           int scanrelid, Plan *outer_plan,
                           StringInfo str, int indent, ExplainState *es);
@@ -116,8 +118,11 @@ static void
 ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
 {
        Plan       *plan;
+       QueryDesc  *queryDesc;
        ExplainState *es;
+       StringInfo      str;
        double          totaltime = 0;
+       struct timeval starttime;
 
        /* planner will not cope with utility statements */
        if (query->commandType == CMD_UTILITY)
@@ -136,41 +141,34 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
        if (plan == NULL)
                return;
 
+       /* We don't support DECLARE CURSOR here */
+       Assert(!query->isPortal);
+
+       gettimeofday(&starttime, NULL);
+
+       /* Create a QueryDesc requesting no output */
+       queryDesc = CreateQueryDesc(query, plan, None, NULL, NULL,
+                                                               stmt->analyze);
+
+       /* call ExecutorStart to prepare the plan for execution */
+       ExecutorStart(queryDesc);
+
        /* Execute the plan for statistics if asked for */
        if (stmt->analyze)
        {
-               struct timeval starttime;
-               struct timeval endtime;
-
-               /*
-                * Set up the instrumentation for the top node. This will cascade
-                * during plan initialisation
-                */
-               plan->instrument = InstrAlloc();
+               /* run the plan */
+               ExecutorRun(queryDesc, ForwardScanDirection, 0L);
 
-               gettimeofday(&starttime, NULL);
-               ProcessQuery(query, plan, None, NULL);
-               CommandCounterIncrement();
-               gettimeofday(&endtime, NULL);
+               /* We can't clean up 'till we're done printing the stats... */
 
-               endtime.tv_sec -= starttime.tv_sec;
-               endtime.tv_usec -= starttime.tv_usec;
-               while (endtime.tv_usec < 0)
-               {
-                       endtime.tv_usec += 1000000;
-                       endtime.tv_sec--;
-               }
-               totaltime = (double) endtime.tv_sec +
-                       (double) endtime.tv_usec / 1000000.0;
+               totaltime += elapsed_time(&starttime);
        }
 
        es = (ExplainState *) palloc0(sizeof(ExplainState));
 
        es->printCost = true;           /* default */
-
-       if (stmt->verbose)
-               es->printNodes = true;
-
+       es->printNodes = stmt->verbose;
+       es->printAnalyze = stmt->analyze;
        es->rtable = query->rtable;
 
        if (es->printNodes)
@@ -193,33 +191,73 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
                }
        }
 
+       str = makeStringInfo();
+
        if (es->printCost)
        {
-               StringInfo      str;
+               explain_outNode(str, plan, queryDesc->planstate,
+                                               NULL, 0, es);
+       }
 
-               str = Explain_PlanToString(plan, es);
+       /*
+        * Close down the query and free resources.  Include time for this
+        * in the total runtime.
+        */
+       gettimeofday(&starttime, NULL);
+
+       ExecutorEnd(queryDesc);
+       CommandCounterIncrement();
+
+       totaltime += elapsed_time(&starttime);
+
+       if (es->printCost)
+       {
                if (stmt->analyze)
                        appendStringInfo(str, "Total runtime: %.2f msec\n",
                                                         1000.0 * totaltime);
                do_text_output_multiline(tstate, str->data);
-               pfree(str->data);
-               pfree(str);
        }
 
+       pfree(str->data);
+       pfree(str);
        pfree(es);
 }
 
+/* Compute elapsed time in seconds since given gettimeofday() timestamp */
+static double
+elapsed_time(struct timeval *starttime)
+{
+       struct timeval endtime;
+
+       gettimeofday(&endtime, NULL);
+
+       endtime.tv_sec -= starttime->tv_sec;
+       endtime.tv_usec -= starttime->tv_usec;
+       while (endtime.tv_usec < 0)
+       {
+               endtime.tv_usec += 1000000;
+               endtime.tv_sec--;
+       }
+       return (double) endtime.tv_sec +
+               (double) endtime.tv_usec / 1000000.0;
+}
 
 /*
  * explain_outNode -
  *       converts a Plan node into ascii string and appends it to 'str'
  *
+ * planstate points to the executor state node corresponding to the plan node.
+ * We need this to get at the instrumentation data (if any) as well as the
+ * list of subplans.
+ *
  * outer_plan, if not null, references another plan node that is the outer
  * side of a join with the current node.  This is only interesting for
  * deciphering runtime keys of an inner indexscan.
  */
 static void
-explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
+explain_outNode(StringInfo str,
+                               Plan *plan, PlanState *planstate,
+                               Plan *outer_plan,
                                int indent, ExplainState *es)
 {
        List       *l;
@@ -410,18 +448,23 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
                                                 plan->startup_cost, plan->total_cost,
                                                 plan->plan_rows, plan->plan_width);
 
-               if (plan->instrument && plan->instrument->nloops > 0)
+               /*
+                * We have to forcibly clean up the instrumentation state because
+                * we haven't done ExecutorEnd yet.  This is pretty grotty ...
+                */
+               InstrEndLoop(planstate->instrument);
+
+               if (planstate->instrument && planstate->instrument->nloops > 0)
                {
-                       double          nloops = plan->instrument->nloops;
+                       double          nloops = planstate->instrument->nloops;
 
                        appendStringInfo(str, " (actual time=%.2f..%.2f rows=%.0f loops=%.0f)",
-                                                        1000.0 * plan->instrument->startup / nloops,
-                                                        1000.0 * plan->instrument->total / nloops,
-                                                        plan->instrument->ntuples / nloops,
-                                                        plan->instrument->nloops);
-                       es->printAnalyze = true;
+                                                        1000.0 * planstate->instrument->startup / nloops,
+                                                        1000.0 * planstate->instrument->total / nloops,
+                                                        planstate->instrument->ntuples / nloops,
+                                                        planstate->instrument->nloops);
                }
-               else if( es->printAnalyze )
+               else if (es->printAnalyze)
                {
                        appendStringInfo(str, " (never executed)");
                }
@@ -538,6 +581,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
        if (plan->initPlan)
        {
                List       *saved_rtable = es->rtable;
+               List       *pslist = planstate->initPlan;
                List       *lst;
 
                for (i = 0; i < indent; i++)
@@ -545,12 +589,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
                appendStringInfo(str, "  InitPlan\n");
                foreach(lst, plan->initPlan)
                {
-                       es->rtable = ((SubPlan *) lfirst(lst))->rtable;
+                       SubPlan    *subplan = (SubPlan *) lfirst(lst);
+                       SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist);
+
+                       es->rtable = subplan->rtable;
                        for (i = 0; i < indent; i++)
                                appendStringInfo(str, "  ");
                        appendStringInfo(str, "    ->  ");
-                       explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL,
+                       explain_outNode(str, subplan->plan,
+                                                       subplanstate->planstate,
+                                                       NULL,
                                                        indent + 4, es);
+                       pslist = lnext(pslist);
                }
                es->rtable = saved_rtable;
        }
@@ -561,7 +611,10 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
                for (i = 0; i < indent; i++)
                        appendStringInfo(str, "  ");
                appendStringInfo(str, "  ->  ");
-               explain_outNode(str, outerPlan(plan), NULL, indent + 3, es);
+               explain_outNode(str, outerPlan(plan),
+                                               outerPlanState(planstate),
+                                               NULL,
+                                               indent + 3, es);
        }
 
        /* righttree */
@@ -570,15 +623,20 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
                for (i = 0; i < indent; i++)
                        appendStringInfo(str, "  ");
                appendStringInfo(str, "  ->  ");
-               explain_outNode(str, innerPlan(plan), outerPlan(plan),
+               explain_outNode(str, innerPlan(plan),
+                                               innerPlanState(planstate),
+                                               outerPlan(plan),
                                                indent + 3, es);
        }
 
        if (IsA(plan, Append))
        {
                Append     *appendplan = (Append *) plan;
+               AppendState *appendstate = (AppendState *) planstate;
                List       *lst;
+               int                     j;
 
+               j = 0;
                foreach(lst, appendplan->appendplans)
                {
                        Plan       *subnode = (Plan *) lfirst(lst);
@@ -587,13 +645,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
                                appendStringInfo(str, "  ");
                        appendStringInfo(str, "  ->  ");
 
-                       explain_outNode(str, subnode, NULL, indent + 3, es);
+                       explain_outNode(str, subnode,
+                                                       appendstate->appendplans[j],
+                                                       NULL,
+                                                       indent + 3, es);
+                       j++;
                }
        }
 
        if (IsA(plan, SubqueryScan))
        {
                SubqueryScan *subqueryscan = (SubqueryScan *) plan;
+               SubqueryScanState *subquerystate = (SubqueryScanState *) planstate;
                Plan       *subnode = subqueryscan->subplan;
                RangeTblEntry *rte = rt_fetch(subqueryscan->scan.scanrelid,
                                                                          es->rtable);
@@ -606,13 +669,16 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
                        appendStringInfo(str, "  ");
                appendStringInfo(str, "  ->  ");
 
-               explain_outNode(str, subnode, NULL, indent + 3, es);
+               explain_outNode(str, subnode,
+                                               subquerystate->subplan,
+                                               NULL,
+                                               indent + 3, es);
 
                es->rtable = saved_rtable;
        }
 
        /* subPlan-s */
-       if (plan->subPlan)
+       if (planstate->subPlan)
        {
                List       *saved_rtable = es->rtable;
                List       *lst;
@@ -620,29 +686,24 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
                for (i = 0; i < indent; i++)
                        appendStringInfo(str, "  ");
                appendStringInfo(str, "  SubPlan\n");
-               foreach(lst, plan->subPlan)
+               foreach(lst, planstate->subPlan)
                {
-                       es->rtable = ((SubPlan *) lfirst(lst))->rtable;
+                       SubPlanState *sps = (SubPlanState *) lfirst(lst);
+                       SubPlan *sp = (SubPlan *) sps->ps.plan;
+
+                       es->rtable = sp->rtable;
                        for (i = 0; i < indent; i++)
                                appendStringInfo(str, "  ");
                        appendStringInfo(str, "    ->  ");
-                       explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL,
+                       explain_outNode(str, sp->plan,
+                                                       sps->planstate,
+                                                       NULL,
                                                        indent + 4, es);
                }
                es->rtable = saved_rtable;
        }
 }
 
-static StringInfo
-Explain_PlanToString(Plan *plan, ExplainState *es)
-{
-       StringInfo      str = makeStringInfo();
-
-       if (plan != NULL)
-               explain_outNode(str, plan, NULL, 0, es);
-       return str;
-}
-
 /*
  * Show a qualifier expression for a scan plan node
  */
index 812cb05..c8607fc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.4 2002/11/13 00:44:08 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.5 2002/12/05 15:50:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 /*
  * PortalCleanup
+ *
+ * Clean up a portal when it's dropped.  Since this mainly exists to run
+ * ExecutorEnd(), it should not be set as the cleanup hook until we have
+ * called ExecutorStart() on the portal's query.
  */
 void
 PortalCleanup(Portal portal)
@@ -43,7 +47,7 @@ PortalCleanup(Portal portal)
        /*
         * tell the executor to shutdown the query
         */
-       ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal));
+       ExecutorEnd(PortalGetQueryDesc(portal));
 
        /*
         * switch back to previous context
@@ -116,7 +120,7 @@ PerformPortalFetch(char *name,
        oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
 
        queryDesc = PortalGetQueryDesc(portal);
-       estate = PortalGetState(portal);
+       estate = queryDesc->estate;
 
        /*
         * If the requested destination is not the same as the query's
@@ -158,7 +162,7 @@ PerformPortalFetch(char *name,
                else
                        direction = ForwardScanDirection;
 
-               ExecutorRun(queryDesc, estate, direction, (long) count);
+               ExecutorRun(queryDesc, direction, (long) count);
 
                if (estate->es_processed > 0)
                        portal->atStart = false;        /* OK to back up now */
@@ -172,7 +176,7 @@ PerformPortalFetch(char *name,
                else
                        direction = BackwardScanDirection;
 
-               ExecutorRun(queryDesc, estate, direction, (long) count);
+               ExecutorRun(queryDesc, direction, (long) count);
 
                if (estate->es_processed > 0)
                        portal->atEnd = false;          /* OK to go forward now */
index 391ef0b..9a570c8 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2002, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.8 2002/11/15 00:47:22 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.9 2002/12/05 15:50:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -49,7 +49,7 @@ static void InitQueryHashTable(void);
 static void StoreQuery(const char *stmt_name, List *query_list,
                   List *plan_list, List *argtype_list);
 static QueryHashEntry *FetchQuery(const char *plan_name);
-static void RunQuery(QueryDesc *qdesc, EState *state);
+static void RunQuery(QueryDesc *qdesc);
 
 
 /*
@@ -151,15 +151,12 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
                else
                {
                        QueryDesc  *qdesc;
-                       EState     *state;
 
                        if (log_executor_stats)
                                ResetUsage();
 
-                       qdesc = CreateQueryDesc(query, plan, outputDest, NULL);
-                       state = CreateExecutorState();
-
-                       state->es_param_list_info = paramLI;
+                       qdesc = CreateQueryDesc(query, plan, outputDest, NULL,
+                                                                       paramLI, false);
 
                        if (stmt->into)
                        {
@@ -170,7 +167,7 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
                                qdesc->dest = None;
                        }
 
-                       RunQuery(qdesc, state);
+                       RunQuery(qdesc);
 
                        if (log_executor_stats)
                                ShowUsage("EXECUTOR STATISTICS");
@@ -334,15 +331,11 @@ FetchQueryParams(const char *plan_name)
  * Actually execute a prepared query.
  */
 static void
-RunQuery(QueryDesc *qdesc, EState *state)
+RunQuery(QueryDesc *qdesc)
 {
-       TupleDesc       tupdesc;
-
-       tupdesc = ExecutorStart(qdesc, state);
-
-       ExecutorRun(qdesc, state, state->es_direction, 0L);
-
-       ExecutorEnd(qdesc, state);
+       ExecutorStart(qdesc);
+       ExecutorRun(qdesc, ForwardScanDirection, 0L);
+       ExecutorEnd(qdesc);
 }
 
 /*
index 0a56c3f..d9b0ea1 100644 (file)
@@ -1,4 +1,4 @@
-$Header: /cvsroot/pgsql/src/backend/executor/README,v 1.1 2001/05/15 00:35:50 tgl Exp $
+$Header: /cvsroot/pgsql/src/backend/executor/README,v 1.2 2002/12/05 15:50:30 tgl Exp $
 
 The Postgres Executor
 ---------------------
@@ -39,6 +39,27 @@ delivered by the plan tree.
 XXX a great deal more documentation needs to be written here...
 
 
+Plan Trees and State Trees
+--------------------------
+
+The plan tree delivered by the planner contains a tree of Plan nodes (struct
+types derived from struct Plan).  Each Plan node may have expression trees
+associated with it, to represent its target list, qualification conditions,
+etc.  During executor startup we build a parallel tree of identical structure
+containing executor state nodes --- every plan and expression node type has
+a corresponding executor state node type.  Each node in the state tree has a
+pointer to its corresponding node in the plan tree, plus executor state data
+as needed to implement that node type.  This arrangement allows the plan
+tree to be completely read-only as far as the executor is concerned: all data
+that is modified during execution is in the state tree.  Read-only plan trees
+make life much simpler for plan caching and reuse.
+
+Altogether there are four classes of nodes used in these trees: Plan nodes,
+their corresponding PlanState nodes, Expr nodes, and their corresponding
+ExprState nodes.  (Actually, there are also List nodes, which are used as
+"glue" in all four kinds of tree.)
+
+
 EvalPlanQual (READ COMMITTED update checking)
 ---------------------------------------------
 
index 1d7bf67..4ac4781 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Id: execAmi.c,v 1.65 2002/11/30 05:21:01 tgl Exp $
+ *     $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.66 2002/12/05 15:50:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "executor/instrument.h"
 #include "executor/nodeAgg.h"
 #include "executor/nodeAppend.h"
+#include "executor/nodeFunctionscan.h"
 #include "executor/nodeGroup.h"
 #include "executor/nodeGroup.h"
 #include "executor/nodeHash.h"
 #include "executor/nodeHashjoin.h"
 #include "executor/nodeIndexscan.h"
-#include "executor/nodeTidscan.h"
 #include "executor/nodeLimit.h"
 #include "executor/nodeMaterial.h"
 #include "executor/nodeMergejoin.h"
 #include "executor/nodeSort.h"
 #include "executor/nodeSubplan.h"
 #include "executor/nodeSubqueryscan.h"
-#include "executor/nodeFunctionscan.h"
+#include "executor/nodeTidscan.h"
 #include "executor/nodeUnique.h"
 
 
 /* ----------------------------------------------------------------
  *             ExecReScan
  *
- *             XXX this should be extended to cope with all the node types..
- *
  *             takes the new expression context as an argument, so that
  *             index scans needn't have their scan keys updated separately
  *             - marcel 09/20/94
  * ----------------------------------------------------------------
  */
 void
-ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScan(PlanState *node, ExprContext *exprCtxt)
 {
+       /* If collecting timing stats, update them */
        if (node->instrument)
                InstrEndLoop(node->instrument);
 
-       if (node->chgParam != NULL) /* Wow! */
+       /* If we have changed parameters, propagate that info */
+       if (node->chgParam != NIL)
        {
                List       *lst;
 
                foreach(lst, node->initPlan)
                {
-                       Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
+                       PlanState  *splan = ((SubPlanState *) lfirst(lst))->planstate;
 
-                       if (splan->extParam != NULL)            /* don't care about child
+                       if (splan->plan->extParam != NIL)       /* don't care about child
                                                                                                 * locParam */
                                SetChangedParamList(splan, node->chgParam);
-                       if (splan->chgParam != NULL)
-                               ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
+                       if (splan->chgParam != NIL)
+                               ExecReScanSetParamPlan((SubPlanState *) lfirst(lst), node);
                }
                foreach(lst, node->subPlan)
                {
-                       Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
+                       PlanState  *splan = ((SubPlanState *) lfirst(lst))->planstate;
 
-                       if (splan->extParam != NULL)
+                       if (splan->plan->extParam != NIL)
                                SetChangedParamList(splan, node->chgParam);
                }
                /* Well. Now set chgParam for left/right trees. */
@@ -85,76 +85,76 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
 
        switch (nodeTag(node))
        {
-               case T_SeqScan:
-                       ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
+               case T_ResultState:
+                       ExecReScanResult((ResultState *) node, exprCtxt);
                        break;
 
-               case T_IndexScan:
-                       ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
+               case T_AppendState:
+                       ExecReScanAppend((AppendState *) node, exprCtxt);
                        break;
 
-               case T_TidScan:
-                       ExecTidReScan((TidScan *) node, exprCtxt, parent);
+               case T_SeqScanState:
+                       ExecSeqReScan((SeqScanState *) node, exprCtxt);
                        break;
 
-               case T_SubqueryScan:
-                       ExecSubqueryReScan((SubqueryScan *) node, exprCtxt, parent);
+               case T_IndexScanState:
+                       ExecIndexReScan((IndexScanState *) node, exprCtxt);
                        break;
 
-               case T_FunctionScan:
-                       ExecFunctionReScan((FunctionScan *) node, exprCtxt, parent);
+               case T_TidScanState:
+                       ExecTidReScan((TidScanState *) node, exprCtxt);
                        break;
 
-               case T_Material:
-                       ExecMaterialReScan((Material *) node, exprCtxt, parent);
+               case T_SubqueryScanState:
+                       ExecSubqueryReScan((SubqueryScanState *) node, exprCtxt);
                        break;
 
-               case T_NestLoop:
-                       ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
+               case T_FunctionScanState:
+                       ExecFunctionReScan((FunctionScanState *) node, exprCtxt);
                        break;
 
-               case T_HashJoin:
-                       ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
+               case T_NestLoopState:
+                       ExecReScanNestLoop((NestLoopState *) node, exprCtxt);
                        break;
 
-               case T_Hash:
-                       ExecReScanHash((Hash *) node, exprCtxt, parent);
+               case T_MergeJoinState:
+                       ExecReScanMergeJoin((MergeJoinState *) node, exprCtxt);
                        break;
 
-               case T_Agg:
-                       ExecReScanAgg((Agg *) node, exprCtxt, parent);
+               case T_HashJoinState:
+                       ExecReScanHashJoin((HashJoinState *) node, exprCtxt);
                        break;
 
-               case T_Group:
-                       ExecReScanGroup((Group *) node, exprCtxt, parent);
+               case T_MaterialState:
+                       ExecMaterialReScan((MaterialState *) node, exprCtxt);
                        break;
 
-               case T_Result:
-                       ExecReScanResult((Result *) node, exprCtxt, parent);
+               case T_SortState:
+                       ExecReScanSort((SortState *) node, exprCtxt);
                        break;
 
-               case T_Unique:
-                       ExecReScanUnique((Unique *) node, exprCtxt, parent);
+               case T_GroupState:
+                       ExecReScanGroup((GroupState *) node, exprCtxt);
                        break;
 
-               case T_SetOp:
-                       ExecReScanSetOp((SetOp *) node, exprCtxt, parent);
+               case T_AggState:
+                       ExecReScanAgg((AggState *) node, exprCtxt);
                        break;
 
-               case T_Limit:
-                       ExecReScanLimit((Limit *) node, exprCtxt, parent);
+               case T_UniqueState:
+                       ExecReScanUnique((UniqueState *) node, exprCtxt);
                        break;
 
-               case T_Sort:
-                       ExecReScanSort((Sort *) node, exprCtxt, parent);
+               case T_HashState:
+                       ExecReScanHash((HashState *) node, exprCtxt);
                        break;
 
-               case T_MergeJoin:
-                       ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
+               case T_SetOpState:
+                       ExecReScanSetOp((SetOpState *) node, exprCtxt);
                        break;
 
-               case T_Append:
-                       ExecReScanAppend((Append *) node, exprCtxt, parent);
+               case T_LimitState:
+                       ExecReScanLimit((LimitState *) node, exprCtxt);
                        break;
 
                default:
@@ -163,10 +163,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
                        return;
        }
 
-       if (node->chgParam != NULL)
+       if (node->chgParam != NIL)
        {
                freeList(node->chgParam);
-               node->chgParam = NULL;
+               node->chgParam = NIL;
        }
 }
 
@@ -176,37 +176,37 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
  * Marks the current scan position.
  */
 void
-ExecMarkPos(Plan *node)
+ExecMarkPos(PlanState *node)
 {
        switch (nodeTag(node))
        {
-               case T_SeqScan:
-                       ExecSeqMarkPos((SeqScan *) node);
+               case T_SeqScanState:
+                       ExecSeqMarkPos((SeqScanState *) node);
                        break;
 
-               case T_IndexScan:
-                       ExecIndexMarkPos((IndexScan *) node);
+               case T_IndexScanState:
+                       ExecIndexMarkPos((IndexScanState *) node);
                        break;
 
-               case T_TidScan:
-                       ExecTidMarkPos((TidScan *) node);
+               case T_TidScanState:
+                       ExecTidMarkPos((TidScanState *) node);
                        break;
 
-               case T_FunctionScan:
-                       ExecFunctionMarkPos((FunctionScan *) node);
+               case T_FunctionScanState:
+                       ExecFunctionMarkPos((FunctionScanState *) node);
                        break;
 
-               case T_Material:
-                       ExecMaterialMarkPos((Material *) node);
+               case T_MaterialState:
+                       ExecMaterialMarkPos((MaterialState *) node);
                        break;
 
-               case T_Sort:
-                       ExecSortMarkPos((Sort *) node);
+               case T_SortState:
+                       ExecSortMarkPos((SortState *) node);
                        break;
 
                default:
                        /* don't make hard error unless caller asks to restore... */
-                       elog(LOG, "ExecMarkPos: node type %d not supported",
+                       elog(DEBUG1, "ExecMarkPos: node type %d not supported",
                                 nodeTag(node));
                        break;
        }
@@ -218,32 +218,32 @@ ExecMarkPos(Plan *node)
  * restores the scan position previously saved with ExecMarkPos()
  */
 void
-ExecRestrPos(Plan *node)
+ExecRestrPos(PlanState *node)
 {
        switch (nodeTag(node))
        {
-               case T_SeqScan:
-                       ExecSeqRestrPos((SeqScan *) node);
+               case T_SeqScanState:
+                       ExecSeqRestrPos((SeqScanState *) node);
                        break;
 
-               case T_IndexScan:
-                       ExecIndexRestrPos((IndexScan *) node);
+               case T_IndexScanState:
+                       ExecIndexRestrPos((IndexScanState *) node);
                        break;
 
-               case T_TidScan:
-                       ExecTidRestrPos((TidScan *) node);
+               case T_TidScanState:
+                       ExecTidRestrPos((TidScanState *) node);
                        break;
 
-               case T_FunctionScan:
-                       ExecFunctionRestrPos((FunctionScan *) node);
+               case T_FunctionScanState:
+                       ExecFunctionRestrPos((FunctionScanState *) node);
                        break;
 
-               case T_Material:
-                       ExecMaterialRestrPos((Material *) node);
+               case T_MaterialState:
+                       ExecMaterialRestrPos((MaterialState *) node);
                        break;
 
-               case T_Sort:
-                       ExecSortRestrPos((Sort *) node);
+               case T_SortState:
+                       ExecSortRestrPos((SortState *) node);
                        break;
 
                default:
@@ -258,6 +258,7 @@ ExecRestrPos(Plan *node)
  *
  * XXX Ideally, all plan node types would support mark/restore, and this
  * wouldn't be needed.  For now, this had better match the routines above.
+ * But note the test is on Plan nodetype, not PlanState nodetype.
  */
 bool
 ExecSupportsMarkRestore(NodeTag plantype)
index 9202666..15d47df 100644 (file)
  *     ExecutorRun() and ExecutorEnd()
  *
  *     These three procedures are the external interfaces to the executor.
- *     In each case, the query descriptor and the execution state is required
- *     as arguments
+ *     In each case, the query descriptor is required as an argument.
  *
- *     ExecutorStart() must be called at the beginning of any execution of any
+ *     ExecutorStart() must be called at the beginning of execution of any
  *     query plan and ExecutorEnd() should always be called at the end of
  *     execution of a plan.
  *
@@ -27,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.189 2002/12/05 04:04:42 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.190 2002/12/05 15:50:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 
 /* decls for local routines only used within this module */
-static TupleDesc InitPlan(CmdType operation,
-                Query *parseTree,
-                Plan *plan,
-                EState *estate);
+static void InitPlan(QueryDesc *queryDesc);
 static void initResultRelInfo(ResultRelInfo *resultRelInfo,
                                  Index resultRelationIndex,
                                  List *rangeTable,
                                  CmdType operation);
-static void EndPlan(Plan *plan, EState *estate);
-static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
+static void EndPlan(PlanState *planstate, EState *estate);
+static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
                        CmdType operation,
                        long numberTuples,
                        ScanDirection direction,
@@ -73,11 +69,6 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
                   EState *estate);
 static TupleTableSlot *EvalPlanQualNext(EState *estate);
 static void EndEvalPlanQual(EState *estate);
-static void ExecCheckQueryPerms(CmdType operation, Query *parseTree,
-                                       Plan *plan);
-static void ExecCheckPlanPerms(Plan *plan, List *rangeTable,
-                                  CmdType operation);
-static void ExecCheckRTPerms(List *rangeTable, CmdType operation);
 static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
 
 /* end of local decls */
@@ -89,26 +80,40 @@ static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
  *             This routine must be called at the beginning of any execution of any
  *             query plan
  *
- *             returns a TupleDesc which describes the attributes of the tuples to
- *             be returned by the query.  (Same value is saved in queryDesc)
+ * Takes a QueryDesc previously created by CreateQueryDesc (it's not real
+ * clear why we bother to separate the two functions, but...).  The tupDesc
+ * field of the QueryDesc is filled in to describe the tuples that will be
+ * returned, and the internal fields (estate and planstate) are set up.
  *
+ * XXX this will change soon:
  * NB: the CurrentMemoryContext when this is called must be the context
  * to be used as the per-query context for the query plan.     ExecutorRun()
  * and ExecutorEnd() must be called in this same memory context.
  * ----------------------------------------------------------------
  */
-TupleDesc
-ExecutorStart(QueryDesc *queryDesc, EState *estate)
+void
+ExecutorStart(QueryDesc *queryDesc)
 {
-       TupleDesc       result;
+       EState     *estate;
 
-       /* sanity checks */
+       /* sanity checks: queryDesc must not be started already */
        Assert(queryDesc != NULL);
+       Assert(queryDesc->estate == NULL);
+
+       /*
+        * Build EState, fill with parameters from queryDesc
+        */
+       estate = CreateExecutorState();
+       queryDesc->estate = estate;
+
+       estate->es_param_list_info = queryDesc->params;
 
        if (queryDesc->plantree->nParamExec > 0)
                estate->es_param_exec_vals = (ParamExecData *)
                        palloc0(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
 
+       estate->es_instrument = queryDesc->doInstrument;
+
        /*
         * Make our own private copy of the current query snapshot data.
         *
@@ -119,16 +124,9 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
        estate->es_snapshot = CopyQuerySnapshot();
 
        /*
-        * Initialize the plan
+        * Initialize the plan state tree
         */
-       result = InitPlan(queryDesc->operation,
-                                         queryDesc->parsetree,
-                                         queryDesc->plantree,
-                                         estate);
-
-       queryDesc->tupDesc = result;
-
-       return result;
+       InitPlan(queryDesc);
 }
 
 /* ----------------------------------------------------------------
@@ -150,11 +148,11 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecutorRun(QueryDesc *queryDesc, EState *estate,
+ExecutorRun(QueryDesc *queryDesc,
                        ScanDirection direction, long count)
 {
        CmdType         operation;
-       Plan       *plan;
+       EState     *estate;
        CommandDest dest;
        DestReceiver *destfunc;
        TupleTableSlot *result;
@@ -169,7 +167,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
         * feature.
         */
        operation = queryDesc->operation;
-       plan = queryDesc->plantree;
+       estate = queryDesc->estate;
        dest = queryDesc->dest;
 
        /*
@@ -189,7 +187,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
                result = NULL;
        else
                result = ExecutePlan(estate,
-                                                        plan,
+                                                        queryDesc->planstate,
                                                         operation,
                                                         count,
                                                         direction,
@@ -211,12 +209,16 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
  * ----------------------------------------------------------------
  */
 void
-ExecutorEnd(QueryDesc *queryDesc, EState *estate)
+ExecutorEnd(QueryDesc *queryDesc)
 {
+       EState     *estate;
+
        /* sanity checks */
        Assert(queryDesc != NULL);
 
-       EndPlan(queryDesc->plantree, estate);
+       estate = queryDesc->estate;
+
+       EndPlan(queryDesc->planstate, estate);
 
        if (estate->es_snapshot != NULL)
        {
@@ -235,97 +237,55 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate)
 
 
 /*
- * ExecCheckQueryPerms
- *             Check access permissions for all relations referenced in a query.
+ * CreateExecutorState
  */
-static void
-ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan)
+EState *
+CreateExecutorState(void)
 {
+       EState     *state;
+
        /*
-        * Check RTEs in the query's primary rangetable.
+        * create a new executor state
         */
-       ExecCheckRTPerms(parseTree->rtable, operation);
+       state = makeNode(EState);
 
        /*
-        * Search for subplans and APPEND nodes to check their rangetables.
+        * initialize the Executor State structure
         */
-       ExecCheckPlanPerms(plan, parseTree->rtable, operation);
-}
-
-/*
- * ExecCheckPlanPerms
- *             Recursively scan the plan tree to check access permissions in
- *             subplans.
- */
-static void
-ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation)
-{
-       List       *subp;
+       state->es_direction = ForwardScanDirection;
+       state->es_range_table = NIL;
 
-       if (plan == NULL)
-               return;
-
-       /* Check subplans, which we assume are plain SELECT queries */
-
-       foreach(subp, plan->initPlan)
-       {
-               SubPlan    *subplan = (SubPlan *) lfirst(subp);
-
-               ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
-               ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
-       }
-       foreach(subp, plan->subPlan)
-       {
-               SubPlan    *subplan = (SubPlan *) lfirst(subp);
+       state->es_result_relations = NULL;
+       state->es_num_result_relations = 0;
+       state->es_result_relation_info = NULL;
 
-               ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
-               ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
-       }
+       state->es_junkFilter = NULL;
 
-       /* Check lower plan nodes */
+       state->es_into_relation_descriptor = NULL;
 
-       ExecCheckPlanPerms(plan->lefttree, rangeTable, operation);
-       ExecCheckPlanPerms(plan->righttree, rangeTable, operation);
+       state->es_param_list_info = NULL;
+       state->es_param_exec_vals = NULL;
 
-       /* Do node-type-specific checks */
+       state->es_tupleTable = NULL;
 
-       switch (nodeTag(plan))
-       {
-               case T_SubqueryScan:
-                       {
-                               SubqueryScan *scan = (SubqueryScan *) plan;
-                               RangeTblEntry *rte;
+       state->es_query_cxt = CurrentMemoryContext;
 
-                               /* Recursively check the subquery */
-                               rte = rt_fetch(scan->scan.scanrelid, rangeTable);
-                               Assert(rte->rtekind == RTE_SUBQUERY);
-                               ExecCheckQueryPerms(operation, rte->subquery, scan->subplan);
-                               break;
-                       }
-               case T_Append:
-                       {
-                               Append     *app = (Append *) plan;
-                               List       *appendplans;
+       state->es_instrument = false;
 
-                               foreach(appendplans, app->appendplans)
-                               {
-                                       ExecCheckPlanPerms((Plan *) lfirst(appendplans),
-                                                                          rangeTable,
-                                                                          operation);
-                               }
-                               break;
-                       }
+       state->es_per_tuple_exprcontext = NULL;
 
-               default:
-                       break;
-       }
+       /*
+        * return the executor state structure
+        */
+       return state;
 }
 
+
 /*
  * ExecCheckRTPerms
  *             Check access permissions for all relations listed in a range table.
  */
-static void
+void
 ExecCheckRTPerms(List *rangeTable, CmdType operation)
 {
        List       *lp;
@@ -350,11 +310,18 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
        AclResult       aclcheck_result;
 
        /*
-        * Only plain-relation RTEs need to be checked here.  Subquery RTEs
-        * will be checked when ExecCheckPlanPerms finds the SubqueryScan
-        * node, and function RTEs are checked by init_fcache when the
-        * function is prepared for execution.  Join and special RTEs need no
-        * checks.
+        * If it's a subquery, recursively examine its rangetable.
+        */
+       if (rte->rtekind == RTE_SUBQUERY)
+       {
+               ExecCheckRTPerms(rte->subquery->rtable, operation);
+               return;
+       }
+
+       /*
+        * Otherwise, only plain-relation RTEs need to be checked here.
+        * Function RTEs are checked by init_fcache when the function is prepared
+        * for execution. Join and special RTEs need no checks.
         */
        if (rte->rtekind != RTE_RELATION)
                return;
@@ -367,7 +334,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
         *
         * Note: GetUserId() is presently fast enough that there's no harm in
         * calling it separately for each RTE.  If that stops being true, we
-        * could call it once in ExecCheckQueryPerms and pass the userid down
+        * could call it once in ExecCheckRTPerms and pass the userid down
         * from there.  But for now, no need for the extra clutter.
         */
        userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
@@ -428,7 +395,8 @@ typedef struct execRowMark
 
 typedef struct evalPlanQual
 {
-       Plan       *plan;
+       Plan       *plan;                       /* XXX temporary */
+       PlanState  *planstate;
        Index           rti;
        EState          estate;
        struct evalPlanQual *free;
@@ -441,17 +409,24 @@ typedef struct evalPlanQual
  *             and start up the rule manager
  * ----------------------------------------------------------------
  */
-static TupleDesc
-InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
+static void
+InitPlan(QueryDesc *queryDesc)
 {
+       CmdType         operation = queryDesc->operation;
+       Query *parseTree = queryDesc->parsetree;
+       Plan *plan = queryDesc->plantree;
+       EState *estate = queryDesc->estate;
+       PlanState  *planstate;
        List       *rangeTable;
        Relation        intoRelationDesc;
        TupleDesc       tupType;
 
        /*
-        * Do permissions checks.
+        * Do permissions checks.  It's sufficient to examine the query's
+        * top rangetable here --- subplan RTEs will be checked during
+        * ExecInitSubPlan().
         */
-       ExecCheckQueryPerms(operation, parseTree, plan);
+       ExecCheckRTPerms(parseTree->rtable, operation);
 
        /*
         * get information from query descriptor
@@ -575,14 +550,14 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
         * query tree.  This opens files, allocates storage and leaves us
         * ready to start processing tuples.
         */
-       ExecInitNode(plan, estate, NULL);
+       planstate = ExecInitNode(plan, estate);
 
        /*
         * Get the tuple descriptor describing the type of tuples to return.
         * (this is especially important if we are creating a relation with
         * "SELECT INTO")
         */
-       tupType = ExecGetTupType(plan);         /* tuple descriptor */
+       tupType = ExecGetTupType(planstate);
 
        /*
         * Initialize the junk filter if needed. SELECT and INSERT queries
@@ -627,26 +602,29 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                         */
                        if (parseTree->resultRelations != NIL)
                        {
-                               List       *subplans;
+                               PlanState **appendplans;
+                               int                     as_nplans;
                                ResultRelInfo *resultRelInfo;
+                               int                     i;
 
                                /* Top plan had better be an Append here. */
                                Assert(IsA(plan, Append));
                                Assert(((Append *) plan)->isTarget);
-                               subplans = ((Append *) plan)->appendplans;
-                               Assert(length(subplans) == estate->es_num_result_relations);
+                               Assert(IsA(planstate, AppendState));
+                               appendplans = ((AppendState *) planstate)->appendplans;
+                               as_nplans = ((AppendState *) planstate)->as_nplans;
+                               Assert(as_nplans == estate->es_num_result_relations);
                                resultRelInfo = estate->es_result_relations;
-                               while (subplans != NIL)
+                               for (i = 0; i < as_nplans; i++)
                                {
-                                       Plan       *subplan = (Plan *) lfirst(subplans);
+                                       PlanState  *subplan = appendplans[i];
                                        JunkFilter *j;
 
-                                       j = ExecInitJunkFilter(subplan->targetlist,
+                                       j = ExecInitJunkFilter(subplan->plan->targetlist,
                                                                                   ExecGetTupType(subplan),
                                                          ExecAllocTableSlot(estate->es_tupleTable));
                                        resultRelInfo->ri_junkFilter = j;
                                        resultRelInfo++;
-                                       subplans = lnext(subplans);
                                }
 
                                /*
@@ -661,7 +639,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                                /* Normal case with just one JunkFilter */
                                JunkFilter *j;
 
-                               j = ExecInitJunkFilter(plan->targetlist,
+                               j = ExecInitJunkFilter(planstate->plan->targetlist,
                                                                           tupType,
                                                          ExecAllocTableSlot(estate->es_tupleTable));
                                estate->es_junkFilter = j;
@@ -755,7 +733,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
 
        estate->es_into_relation_descriptor = intoRelationDesc;
 
-       return tupType;
+       queryDesc->tupDesc = tupType;
+       queryDesc->planstate = planstate;
 }
 
 /*
@@ -816,11 +795,11 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
 /* ----------------------------------------------------------------
  *             EndPlan
  *
- *             Cleans up the query plan -- closes files and free up storages
+ *             Cleans up the query plan -- closes files and frees up storage
  * ----------------------------------------------------------------
  */
 static void
-EndPlan(Plan *plan, EState *estate)
+EndPlan(PlanState *planstate, EState *estate)
 {
        ResultRelInfo *resultRelInfo;
        int                     i;
@@ -835,7 +814,7 @@ EndPlan(Plan *plan, EState *estate)
        /*
         * shut down the node-type-specific query processing
         */
-       ExecEndNode(plan, NULL);
+       ExecEndNode(planstate);
 
        /*
         * destroy the executor "tuple" table.
@@ -902,7 +881,7 @@ EndPlan(Plan *plan, EState *estate)
  */
 static TupleTableSlot *
 ExecutePlan(EState *estate,
-                       Plan *plan,
+                       PlanState *planstate,
                        CmdType operation,
                        long numberTuples,
                        ScanDirection direction,
@@ -964,10 +943,10 @@ lnext:    ;
                {
                        slot = EvalPlanQualNext(estate);
                        if (TupIsNull(slot))
-                               slot = ExecProcNode(plan, NULL);
+                               slot = ExecProcNode(planstate);
                }
                else
-                       slot = ExecProcNode(plan, NULL);
+                       slot = ExecProcNode(planstate);
 
                /*
                 * if the tuple is null, then we assume there is nothing more to
@@ -1765,7 +1744,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
                        oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
                        Assert(oldepq->rti != 0);
                        /* stop execution */
-                       ExecEndNode(epq->plan, NULL);
+                       ExecEndNode(epq->planstate);
                        ExecDropTupleTable(epqstate->es_tupleTable, true);
                        epqstate->es_tupleTable = NULL;
                        heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
@@ -1793,10 +1772,8 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
 
                        /*
                         * Each stack level has its own copy of the plan tree.  This
-                        * is wasteful, but necessary as long as plan nodes point to
-                        * exec state nodes rather than vice versa.  Note that
-                        * copyfuncs.c doesn't attempt to copy the exec state nodes,
-                        * which is a good thing in this situation.
+                        * is wasteful, but necessary until plan trees are fully
+                        * read-only.
                         */
                        newepq->plan = copyObject(estate->es_origPlan);
 
@@ -1858,7 +1835,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
        if (endNode)
        {
                /* stop execution */
-               ExecEndNode(epq->plan, NULL);
+               ExecEndNode(epq->planstate);
                ExecDropTupleTable(epqstate->es_tupleTable, true);
                epqstate->es_tupleTable = NULL;
        }
@@ -1886,7 +1863,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
        epqstate->es_tupleTable =
                ExecCreateTupleTable(estate->es_tupleTable->size);
 
-       ExecInitNode(epq->plan, epqstate, NULL);
+       epq->planstate = ExecInitNode(epq->plan, epqstate);
 
        return EvalPlanQualNext(estate);
 }
@@ -1902,7 +1879,7 @@ EvalPlanQualNext(EState *estate)
        Assert(epq->rti != 0);
 
 lpqnext:;
-       slot = ExecProcNode(epq->plan, NULL);
+       slot = ExecProcNode(epq->planstate);
 
        /*
         * No more tuples for this PQ. Continue previous one.
@@ -1910,7 +1887,7 @@ lpqnext:;
        if (TupIsNull(slot))
        {
                /* stop execution */
-               ExecEndNode(epq->plan, NULL);
+               ExecEndNode(epq->planstate);
                ExecDropTupleTable(epqstate->es_tupleTable, true);
                epqstate->es_tupleTable = NULL;
                heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
@@ -1951,7 +1928,7 @@ EndEvalPlanQual(EState *estate)
        for (;;)
        {
                /* stop execution */
-               ExecEndNode(epq->plan, NULL);
+               ExecEndNode(epq->planstate);
                ExecDropTupleTable(epqstate->es_tupleTable, true);
                epqstate->es_tupleTable = NULL;
                if (epqstate->es_evTuple[epq->rti - 1] != NULL)
index 2054a6c..2db4a14 100644 (file)
@@ -5,23 +5,23 @@
  *      "get a tuple", and "cleanup" routines for the given node type.
  *      If the node has children, then it will presumably call ExecInitNode,
  *      ExecProcNode, or ExecEndNode on its subnodes and do the appropriate
- *      processing..
+ *      processing.
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.30 2002/06/20 20:29:27 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.31 2002/12/05 15:50:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /*
  *      INTERFACE ROUTINES
+ *             ExecCountSlotsNode -    count tuple slots needed by plan tree
  *             ExecInitNode    -               initialize a plan node and its subplans
  *             ExecProcNode    -               get a tuple by executing the plan node
  *             ExecEndNode             -               shut down a plan node and its subplans
- *             ExecCountSlotsNode -    count tuple slots needed by plan tree
  *             ExecGetTupType  -               get result tuple type of a plan node
  *
  *      NOTES
  *       * ExecInitNode() notices that it is looking at a nest loop and
  *             as the code below demonstrates, it calls ExecInitNestLoop().
  *             Eventually this calls ExecInitNode() on the right and left subplans
- *             and so forth until the entire plan is initialized.
+ *             and so forth until the entire plan is initialized.  The result
+ *             of ExecInitNode() is a plan state tree built with the same structure
+ *             as the underlying plan tree.
  *
- *       * Then when ExecRun() is called, it calls ExecutePlan() which
- *             calls ExecProcNode() repeatedly on the top node of the plan.
+ *       * Then when ExecRun() is called, it calls ExecutePlan() which calls
+ *             ExecProcNode() repeatedly on the top node of the plan state tree.
  *             Each time this happens, ExecProcNode() will end up calling
  *             ExecNestLoop(), which calls ExecProcNode() on its subplans.
  *             Each of these subplans is a sequential scan so ExecSeqScan() is
@@ -73,7 +75,6 @@
  *             ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch
  *             their work to the appopriate node support routines which may
  *             in turn call these routines themselves on their subplans.
- *
  */
 #include "postgres.h"
 
 #include "executor/instrument.h"
 #include "executor/nodeAgg.h"
 #include "executor/nodeAppend.h"
+#include "executor/nodeFunctionscan.h"
 #include "executor/nodeGroup.h"
 #include "executor/nodeHash.h"
 #include "executor/nodeHashjoin.h"
 #include "executor/nodeIndexscan.h"
-#include "executor/nodeTidscan.h"
 #include "executor/nodeLimit.h"
 #include "executor/nodeMaterial.h"
 #include "executor/nodeMergejoin.h"
@@ -96,7 +97,7 @@
 #include "executor/nodeSort.h"
 #include "executor/nodeSubplan.h"
 #include "executor/nodeSubqueryscan.h"
-#include "executor/nodeFunctionscan.h"
+#include "executor/nodeTidscan.h"
 #include "executor/nodeUnique.h"
 #include "miscadmin.h"
 #include "tcop/tcopprot.h"
  *
  *             Initial States:
  *               'node' is the plan produced by the query planner
+ *               'estate' is the shared execution state for the query tree
  *
- *             returns TRUE/FALSE on whether the plan was successfully initialized
+ *             Returns a PlanState node corresponding to the given Plan node.
  * ------------------------------------------------------------------------
  */
-bool
-ExecInitNode(Plan *node, EState *estate, Plan *parent)
+PlanState *
+ExecInitNode(Plan *node, EState *estate)
 {
-       bool            result;
+       PlanState  *result;
+       List       *subps;
        List       *subp;
 
        /*
         * do nothing when we get to the end of a leaf on tree.
         */
        if (node == NULL)
-               return FALSE;
-
-       /* Set up instrumentation for this node if the parent has it */
-       if (!node->instrument && parent && parent->instrument)
-               node->instrument = InstrAlloc();
-
-       foreach(subp, node->initPlan)
-       {
-               result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
-               if (result == FALSE)
-                       return FALSE;
-       }
+               return NULL;
 
        switch (nodeTag(node))
        {
@@ -142,104 +134,124 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
                         * control nodes
                         */
                case T_Result:
-                       result = ExecInitResult((Result *) node, estate, parent);
+                       result = (PlanState *) ExecInitResult((Result *) node, estate);
                        break;
 
                case T_Append:
-                       result = ExecInitAppend((Append *) node, estate, parent);
+                       result = (PlanState *) ExecInitAppend((Append *) node, estate);
                        break;
 
                        /*
                         * scan nodes
                         */
                case T_SeqScan:
-                       result = ExecInitSeqScan((SeqScan *) node, estate, parent);
+                       result = (PlanState *) ExecInitSeqScan((SeqScan *) node, estate);
                        break;
 
                case T_IndexScan:
-                       result = ExecInitIndexScan((IndexScan *) node, estate, parent);
+                       result = (PlanState *) ExecInitIndexScan((IndexScan *) node, estate);
                        break;
 
                case T_TidScan:
-                       result = ExecInitTidScan((TidScan *) node, estate, parent);
+                       result = (PlanState *) ExecInitTidScan((TidScan *) node, estate);
                        break;
 
                case T_SubqueryScan:
-                       result = ExecInitSubqueryScan((SubqueryScan *) node, estate,
-                                                                                 parent);
+                       result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node, estate);
                        break;
 
                case T_FunctionScan:
-                       result = ExecInitFunctionScan((FunctionScan *) node, estate,
-                                                                                 parent);
+                       result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node, estate);
                        break;
 
                        /*
                         * join nodes
                         */
                case T_NestLoop:
-                       result = ExecInitNestLoop((NestLoop *) node, estate, parent);
+                       result = (PlanState *) ExecInitNestLoop((NestLoop *) node, estate);
                        break;
 
                case T_MergeJoin:
-                       result = ExecInitMergeJoin((MergeJoin *) node, estate, parent);
-                       break;
-
-               case T_Hash:
-                       result = ExecInitHash((Hash *) node, estate, parent);
+                       result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node, estate);
                        break;
 
                case T_HashJoin:
-                       result = ExecInitHashJoin((HashJoin *) node, estate, parent);
+                       result = (PlanState *) ExecInitHashJoin((HashJoin *) node, estate);
                        break;
 
                        /*
                         * materialization nodes
                         */
                case T_Material:
-                       result = ExecInitMaterial((Material *) node, estate, parent);
+                       result = (PlanState *) ExecInitMaterial((Material *) node, estate);
                        break;
 
                case T_Sort:
-                       result = ExecInitSort((Sort *) node, estate, parent);
+                       result = (PlanState *) ExecInitSort((Sort *) node, estate);
                        break;
 
-               case T_Unique:
-                       result = ExecInitUnique((Unique *) node, estate, parent);
+               case T_Group:
+                       result = (PlanState *) ExecInitGroup((Group *) node, estate);
                        break;
 
-               case T_SetOp:
-                       result = ExecInitSetOp((SetOp *) node, estate, parent);
+               case T_Agg:
+                       result = (PlanState *) ExecInitAgg((Agg *) node, estate);
                        break;
 
-               case T_Limit:
-                       result = ExecInitLimit((Limit *) node, estate, parent);
+               case T_Unique:
+                       result = (PlanState *) ExecInitUnique((Unique *) node, estate);
                        break;
 
-               case T_Group:
-                       result = ExecInitGroup((Group *) node, estate, parent);
+               case T_Hash:
+                       result = (PlanState *) ExecInitHash((Hash *) node, estate);
                        break;
 
-               case T_Agg:
-                       result = ExecInitAgg((Agg *) node, estate, parent);
+               case T_SetOp:
+                       result = (PlanState *) ExecInitSetOp((SetOp *) node, estate);
+                       break;
+
+               case T_Limit:
+                       result = (PlanState *) ExecInitLimit((Limit *) node, estate);
                        break;
 
                default:
                        elog(ERROR, "ExecInitNode: node type %d unsupported",
                                 (int) nodeTag(node));
-                       result = FALSE;
+                       result = NULL;          /* keep compiler quiet */
                        break;
        }
 
-       if (result != FALSE)
+       /*
+        * Initialize any initPlans present in this node.  The planner put
+        * them in a separate list for us.
+        */
+       subps = NIL;
+       foreach(subp, node->initPlan)
        {
-               foreach(subp, node->subPlan)
-               {
-                       result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
-                       if (result == FALSE)
-                               return FALSE;
-               }
+               SubPlan    *subplan = (SubPlan *) lfirst(subp);
+
+               Assert(IsA(subplan, SubPlan));
+               subps = lappend(subps, ExecInitSubPlan(subplan, estate));
        }
+       result->initPlan = subps;
+
+       /*
+        * Initialize any subPlans present in this node.  These were found
+        * by ExecInitExpr during initialization of the PlanState.
+        */
+       subps = NIL;
+       foreach(subp, result->subPlan)
+       {
+               SubPlan    *subplan = (SubPlan *) lfirst(subp);
+
+               Assert(IsA(subplan, SubPlan));
+               subps = lappend(subps, ExecInitSubPlan(subplan, estate));
+       }
+       result->subPlan = subps;
+
+       /* Set up instrumentation for this node if requested */
+       if (estate->es_instrument)
+               result->instrument = InstrAlloc();
 
        return result;
 }
@@ -248,12 +260,11 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
 /* ----------------------------------------------------------------
  *             ExecProcNode
  *
- *             Initial States:
- *               the query tree must be initialized once by calling ExecInit.
+ *             Execute the given node to return a(nother) tuple.
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecProcNode(Plan *node, Plan *parent)
+ExecProcNode(PlanState *node)
 {
        TupleTableSlot *result;
 
@@ -265,8 +276,8 @@ ExecProcNode(Plan *node, Plan *parent)
        if (node == NULL)
                return NULL;
 
-       if (node->chgParam != NULL) /* something changed */
-               ExecReScan(node, NULL, parent); /* let ReScan handle this */
+       if (node->chgParam != NIL)      /* something changed */
+               ExecReScan(node, NULL); /* let ReScan handle this */
 
        if (node->instrument)
                InstrStartNode(node->instrument);
@@ -276,85 +287,85 @@ ExecProcNode(Plan *node, Plan *parent)
                        /*
                         * control nodes
                         */
-               case T_Result:
-                       result = ExecResult((Result *) node);
+               case T_ResultState:
+                       result = ExecResult((ResultState *) node);
                        break;
 
-               case T_Append:
-                       result = ExecProcAppend((Append *) node);
+               case T_AppendState:
+                       result = ExecProcAppend((AppendState *) node);
                        break;
 
                        /*
                         * scan nodes
                         */
-               case T_SeqScan:
-                       result = ExecSeqScan((SeqScan *) node);
+               case T_SeqScanState:
+                       result = ExecSeqScan((SeqScanState *) node);
                        break;
 
-               case T_IndexScan:
-                       result = ExecIndexScan((IndexScan *) node);
+               case T_IndexScanState:
+                       result = ExecIndexScan((IndexScanState *) node);
                        break;
 
-               case T_TidScan:
-                       result = ExecTidScan((TidScan *) node);
+               case T_TidScanState:
+                       result = ExecTidScan((TidScanState *) node);
                        break;
 
-               case T_SubqueryScan:
-                       result = ExecSubqueryScan((SubqueryScan *) node);
+               case T_SubqueryScanState:
+                       result = ExecSubqueryScan((SubqueryScanState *) node);
                        break;
 
-               case T_FunctionScan:
-                       result = ExecFunctionScan((FunctionScan *) node);
+               case T_FunctionScanState:
+                       result = ExecFunctionScan((FunctionScanState *) node);
                        break;
 
                        /*
                         * join nodes
                         */
-               case T_NestLoop:
-                       result = ExecNestLoop((NestLoop *) node);
+               case T_NestLoopState:
+                       result = ExecNestLoop((NestLoopState *) node);
                        break;
 
-               case T_MergeJoin:
-                       result = ExecMergeJoin((MergeJoin *) node);
+               case T_MergeJoinState:
+                       result = ExecMergeJoin((MergeJoinState *) node);
                        break;
 
-               case T_Hash:
-                       result = ExecHash((Hash *) node);
-                       break;
-
-               case T_HashJoin:
-                       result = ExecHashJoin((HashJoin *) node);
+               case T_HashJoinState:
+                       result = ExecHashJoin((HashJoinState *) node);
                        break;
 
                        /*
                         * materialization nodes
                         */
-               case T_Material:
-                       result = ExecMaterial((Material *) node);
+               case T_MaterialState:
+                       result = ExecMaterial((MaterialState *) node);
                        break;
 
-               case T_Sort:
-                       result = ExecSort((Sort *) node);
+               case T_SortState:
+                       result = ExecSort((SortState *) node);
                        break;
 
-               case T_Unique:
-                       result = ExecUnique((Unique *) node);
+               case T_GroupState:
+                       result = ExecGroup((GroupState *) node);
                        break;
 
-               case T_SetOp:
-                       result = ExecSetOp((SetOp *) node);
+               case T_AggState:
+                       result = ExecAgg((AggState *) node);
                        break;
 
-               case T_Limit:
-                       result = ExecLimit((Limit *) node);
+               case T_UniqueState:
+                       result = ExecUnique((UniqueState *) node);
                        break;
 
-               case T_Group:
-                       result = ExecGroup((Group *) node);
+               case T_HashState:
+                       result = ExecHash((HashState *) node);
                        break;
 
-               case T_Agg:
-                       result = ExecAgg((Agg *) node);
+               case T_SetOpState:
+                       result = ExecSetOp((SetOpState *) node);
+                       break;
+
+               case T_LimitState:
+                       result = ExecLimit((LimitState *) node);
                        break;
 
                default:
@@ -370,10 +381,16 @@ ExecProcNode(Plan *node, Plan *parent)
        return result;
 }
 
+/*
+ * ExecCountSlotsNode - count up the number of tuple table slots needed
+ *
+ * Note that this scans a Plan tree, not a PlanState tree, because we
+ * haven't built the PlanState tree yet ...
+ */
 int
 ExecCountSlotsNode(Plan *node)
 {
-       if (node == (Plan *) NULL)
+       if (node == NULL)
                return 0;
 
        switch (nodeTag(node))
@@ -414,9 +431,6 @@ ExecCountSlotsNode(Plan *node)
                case T_MergeJoin:
                        return ExecCountSlotsMergeJoin((MergeJoin *) node);
 
-               case T_Hash:
-                       return ExecCountSlotsHash((Hash *) node);
-
                case T_HashJoin:
                        return ExecCountSlotsHashJoin((HashJoin *) node);
 
@@ -429,26 +443,30 @@ ExecCountSlotsNode(Plan *node)
                case T_Sort:
                        return ExecCountSlotsSort((Sort *) node);
 
+               case T_Group:
+                       return ExecCountSlotsGroup((Group *) node);
+
+               case T_Agg:
+                       return ExecCountSlotsAgg((Agg *) node);
+
                case T_Unique:
                        return ExecCountSlotsUnique((Unique *) node);
 
+               case T_Hash:
+                       return ExecCountSlotsHash((Hash *) node);
+
                case T_SetOp:
                        return ExecCountSlotsSetOp((SetOp *) node);
 
                case T_Limit:
                        return ExecCountSlotsLimit((Limit *) node);
 
-               case T_Group:
-                       return ExecCountSlotsGroup((Group *) node);
-
-               case T_Agg:
-                       return ExecCountSlotsAgg((Agg *) node);
-
                default:
                        elog(ERROR, "ExecCountSlotsNode: node type %d unsupported",
                                 (int) nodeTag(node));
                        break;
        }
+
        return 0;
 }
 
@@ -464,7 +482,7 @@ ExecCountSlotsNode(Plan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndNode(Plan *node, Plan *parent)
+ExecEndNode(PlanState *node)
 {
        List       *subp;
 
@@ -474,14 +492,19 @@ ExecEndNode(Plan *node, Plan *parent)
        if (node == NULL)
                return;
 
+       if (node->instrument)
+               InstrEndLoop(node->instrument);
+
+       /* Clean up initPlans and subPlans */
        foreach(subp, node->initPlan)
-               ExecEndSubPlan((SubPlan *) lfirst(subp));
+               ExecEndSubPlan((SubPlanState *) lfirst(subp));
        foreach(subp, node->subPlan)
-               ExecEndSubPlan((SubPlan *) lfirst(subp));
-       if (node->chgParam != NULL)
+               ExecEndSubPlan((SubPlanState *) lfirst(subp));
+
+       if (node->chgParam != NIL)
        {
                freeList(node->chgParam);
-               node->chgParam = NULL;
+               node->chgParam = NIL;
        }
 
        switch (nodeTag(node))
@@ -489,85 +512,85 @@ ExecEndNode(Plan *node, Plan *parent)
                        /*
                         * control nodes
                         */
-               case T_Result:
-                       ExecEndResult((Result *) node);
+               case T_ResultState:
+                       ExecEndResult((ResultState *) node);
                        break;
 
-               case T_Append:
-                       ExecEndAppend((Append *) node);
+               case T_AppendState:
+                       ExecEndAppend((AppendState *) node);
                        break;
 
                        /*
                         * scan nodes
                         */
-               case T_SeqScan:
-                       ExecEndSeqScan((SeqScan *) node);
+               case T_SeqScanState:
+                       ExecEndSeqScan((SeqScanState *) node);
                        break;
 
-               case T_IndexScan:
-                       ExecEndIndexScan((IndexScan *) node);
+               case T_IndexScanState:
+                       ExecEndIndexScan((IndexScanState *) node);
                        break;
 
-               case T_TidScan:
-                       ExecEndTidScan((TidScan *) node);
+               case T_TidScanState:
+                       ExecEndTidScan((TidScanState *) node);
                        break;
 
-               case T_SubqueryScan:
-                       ExecEndSubqueryScan((SubqueryScan *) node);
+               case T_SubqueryScanState:
+                       ExecEndSubqueryScan((SubqueryScanState *) node);
                        break;
 
-               case T_FunctionScan:
-                       ExecEndFunctionScan((FunctionScan *) node);
+               case T_FunctionScanState:
+                       ExecEndFunctionScan((FunctionScanState *) node);
                        break;
 
                        /*
                         * join nodes
                         */
-               case T_NestLoop:
-                       ExecEndNestLoop((NestLoop *) node);
-                       break;
-
-               case T_MergeJoin:
-                       ExecEndMergeJoin((MergeJoin *) node);
+               case T_NestLoopState:
+                       ExecEndNestLoop((NestLoopState *) node);
                        break;
 
-               case T_Hash:
-                       ExecEndHash((Hash *) node);
+               case T_MergeJoinState:
+                       ExecEndMergeJoin((MergeJoinState *) node);
                        break;
 
-               case T_HashJoin:
-                       ExecEndHashJoin((HashJoin *) node);
+               case T_HashJoinState:
+                       ExecEndHashJoin((HashJoinState *) node);
                        break;
 
                        /*
                         * materialization nodes
                         */
-               case T_Material:
-                       ExecEndMaterial((Material *) node);
+               case T_MaterialState:
+                       ExecEndMaterial((MaterialState *) node);
                        break;
 
-               case T_Sort:
-                       ExecEndSort((Sort *) node);
+               case T_SortState:
+                       ExecEndSort((SortState *) node);
                        break;
 
-               case T_Unique:
-                       ExecEndUnique((Unique *) node);
+               case T_GroupState:
+                       ExecEndGroup((GroupState *) node);
                        break;
 
-               case T_SetOp:
-                       ExecEndSetOp((SetOp *) node);
+               case T_AggState:
+                       ExecEndAgg((AggState *) node);
                        break;
 
-               case T_Limit:
-                       ExecEndLimit((Limit *) node);
+               case T_UniqueState:
+                       ExecEndUnique((UniqueState *) node);
                        break;
 
-               case T_Group:
-                       ExecEndGroup((Group *) node);
+               case T_HashState:
+                       ExecEndHash((HashState *) node);
                        break;
 
-               case T_Agg:
-                       ExecEndAgg((Agg *) node);
+               case T_SetOpState:
+                       ExecEndSetOp((SetOpState *) node);
+                       break;
+
+               case T_LimitState:
+                       ExecEndLimit((LimitState *) node);
                        break;
 
                default:
@@ -575,9 +598,6 @@ ExecEndNode(Plan *node, Plan *parent)
                                 (int) nodeTag(node));
                        break;
        }
-
-       if (node->instrument)
-               InstrEndLoop(node->instrument);
 }
 
 
@@ -592,7 +612,7 @@ ExecEndNode(Plan *node, Plan *parent)
  * ----------------------------------------------------------------
  */
 TupleDesc
-ExecGetTupType(Plan *node)
+ExecGetTupType(PlanState *node)
 {
        TupleTableSlot *slot;
 
@@ -601,147 +621,147 @@ ExecGetTupType(Plan *node)
 
        switch (nodeTag(node))
        {
-               case T_Result:
+               case T_ResultState:
                        {
-                               ResultState *resstate = ((Result *) node)->resstate;
+                               ResultState *resstate = (ResultState *) node;
 
-                               slot = resstate->cstate.cs_ResultTupleSlot;
+                               slot = resstate->ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_SeqScan:
+               case T_AppendState:
                        {
-                               CommonScanState *scanstate = ((SeqScan *) node)->scanstate;
+                               AppendState *appendstate = (AppendState *) node;
 
-                               slot = scanstate->cstate.cs_ResultTupleSlot;
+                               slot = appendstate->ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_NestLoop:
+               case T_SeqScanState:
                        {
-                               NestLoopState *nlstate = ((NestLoop *) node)->nlstate;
+                               SeqScanState *scanstate = (SeqScanState *) node;
 
-                               slot = nlstate->jstate.cs_ResultTupleSlot;
+                               slot = scanstate->ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_Append:
+               case T_IndexScanState:
                        {
-                               AppendState *appendstate = ((Append *) node)->appendstate;
+                               IndexScanState *scanstate = (IndexScanState *) node;
 
-                               slot = appendstate->cstate.cs_ResultTupleSlot;
+                               slot = scanstate->ss.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_IndexScan:
+               case T_TidScanState:
                        {
-                               CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate;
+                               TidScanState *scanstate = (TidScanState *) node;
 
-                               slot = scanstate->cstate.cs_ResultTupleSlot;
+                               slot = scanstate->ss.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_TidScan:
+               case T_SubqueryScanState:
                        {
-                               CommonScanState *scanstate = ((TidScan *) node)->scan.scanstate;
+                               SubqueryScanState *scanstate = (SubqueryScanState *) node;
 
-                               slot = scanstate->cstate.cs_ResultTupleSlot;
+                               slot = scanstate->ss.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_SubqueryScan:
+               case T_FunctionScanState:
                        {
-                               CommonScanState *scanstate = ((SubqueryScan *) node)->scan.scanstate;
+                               FunctionScanState *scanstate = (FunctionScanState *) node;
 
-                               slot = scanstate->cstate.cs_ResultTupleSlot;
+                               slot = scanstate->ss.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_FunctionScan:
+               case T_NestLoopState:
                        {
-                               CommonScanState *scanstate = ((FunctionScan *) node)->scan.scanstate;
+                               NestLoopState *nlstate = (NestLoopState *) node;
 
-                               slot = scanstate->cstate.cs_ResultTupleSlot;
+                               slot = nlstate->js.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_Material:
+               case T_MergeJoinState:
                        {
-                               MaterialState *matstate = ((Material *) node)->matstate;
+                               MergeJoinState *mergestate = (MergeJoinState *) node;
 
-                               slot = matstate->csstate.css_ScanTupleSlot;
+                               slot = mergestate->js.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_Sort:
+               case T_HashJoinState:
                        {
-                               SortState  *sortstate = ((Sort *) node)->sortstate;
+                               HashJoinState *hashjoinstate = (HashJoinState *) node;
 
-                               slot = sortstate->csstate.css_ScanTupleSlot;
+                               slot = hashjoinstate->js.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_Agg:
+               case T_MaterialState:
                        {
-                               AggState   *aggstate = ((Agg *) node)->aggstate;
+                               MaterialState *matstate = (MaterialState *) node;
 
-                               slot = aggstate->csstate.cstate.cs_ResultTupleSlot;
+                               slot = matstate->ss.ss_ScanTupleSlot;
                        }
                        break;
 
-               case T_Group:
+               case T_SortState:
                        {
-                               GroupState *grpstate = ((Group *) node)->grpstate;
+                               SortState  *sortstate = (SortState *) node;
 
-                               slot = grpstate->csstate.cstate.cs_ResultTupleSlot;
+                               slot = sortstate->ss.ss_ScanTupleSlot;
                        }
                        break;
 
-               case T_Hash:
+               case T_GroupState:
                        {
-                               HashState  *hashstate = ((Hash *) node)->hashstate;
+                               GroupState *grpstate = (GroupState *) node;
 
-                               slot = hashstate->cstate.cs_ResultTupleSlot;
+                               slot = grpstate->ss.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_Unique:
+               case T_AggState:
                        {
-                               UniqueState *uniquestate = ((Unique *) node)->uniquestate;
+                               AggState   *aggstate = (AggState *) node;
 
-                               slot = uniquestate->cstate.cs_ResultTupleSlot;
+                               slot = aggstate->ss.ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_SetOp:
+               case T_UniqueState:
                        {
-                               SetOpState *setopstate = ((SetOp *) node)->setopstate;
+                               UniqueState *uniquestate = (UniqueState *) node;
 
-                               slot = setopstate->cstate.cs_ResultTupleSlot;
+                               slot = uniquestate->ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_Limit:
+               case T_HashState:
                        {
-                               LimitState *limitstate = ((Limit *) node)->limitstate;
+                               HashState  *hashstate = (HashState *) node;
 
-                               slot = limitstate->cstate.cs_ResultTupleSlot;
+                               slot = hashstate->ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_MergeJoin:
+               case T_SetOpState:
                        {
-                               MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate;
+                               SetOpState *setopstate = (SetOpState *) node;
 
-                               slot = mergestate->jstate.cs_ResultTupleSlot;
+                               slot = setopstate->ps.ps_ResultTupleSlot;
                        }
                        break;
 
-               case T_HashJoin:
+               case T_LimitState:
                        {
-                               HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate;
+                               LimitState *limitstate = (LimitState *) node;
 
-                               slot = hashjoinstate->jstate.cs_ResultTupleSlot;
+                               slot = limitstate->ps.ps_ResultTupleSlot;
                        }
                        break;
 
index cb31c02..e7c724c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.112 2002/12/01 20:27:32 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.113 2002/12/05 15:50:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1766,7 +1766,8 @@ ExecEvalExpr(Node *expression,
                                                                                                        isNull, isDone);
                                                break;
                                        case SUBPLAN_EXPR:
-                                               retDatum = ExecSubPlan((SubPlan *) expr->oper,
+                                               /* XXX temporary hack to find exec state node */
+                                               retDatum = ExecSubPlan(((SubPlan *) expr->oper)->pstate,
                                                                                           expr->args, econtext,
                                                                                           isNull);
                                                break;
@@ -1850,6 +1851,169 @@ ExecEvalExprSwitchContext(Node *expression,
 }
 
 
+/*
+ * ExecInitExpr: prepare an expression tree for execution
+ *
+ *     'node' is the root of the expression tree to examine
+ *     'parent' is the PlanState node that owns the expression,
+ *             or NULL if we are preparing an expression that is not associated
+ *             with a plan.  (If so, it can't have Aggrefs or SubPlans.)
+ *
+ * Soon this will generate an expression state tree paralleling the given
+ * expression tree.  Right now, it just searches the expression tree for
+ * Aggref and SubPlan nodes.
+ */
+Node *
+ExecInitExpr(Node *node, PlanState *parent)
+{
+       List       *temp;
+
+       if (node == NULL)
+               return NULL;
+       switch (nodeTag(node))
+       {
+               case T_Var:
+                       break;
+               case T_Const:
+                       break;
+               case T_Param:
+                       break;
+               case T_Aggref:
+                       if (parent && IsA(parent, AggState))
+                       {
+                               AggState   *aggstate = (AggState *) parent;
+                               int                     naggs;
+
+                               aggstate->aggs = lcons(node, aggstate->aggs);
+                               naggs = ++aggstate->numaggs;
+
+                               ExecInitExpr(((Aggref *) node)->target, parent);
+
+                               /*
+                                * Complain if the aggregate's argument contains any
+                                * aggregates; nested agg functions are semantically
+                                * nonsensical.  (This probably was caught earlier,
+                                * but we defend against it here anyway.)
+                                */
+                               if (naggs != aggstate->numaggs)
+                                       elog(ERROR, "Aggregate function calls may not be nested");
+                       }
+                       else
+                               elog(ERROR, "ExecInitExpr: Aggref not expected here");
+                       break;
+               case T_ArrayRef:
+                       {
+                               ArrayRef   *aref = (ArrayRef *) node;
+
+                               ExecInitExpr((Node *) aref->refupperindexpr, parent);
+                               ExecInitExpr((Node *) aref->reflowerindexpr, parent);
+                               ExecInitExpr(aref->refexpr, parent);
+                               ExecInitExpr(aref->refassgnexpr, parent);
+                       }
+                       break;
+               case T_Expr:
+                       {
+                               Expr       *expr = (Expr *) node;
+
+                               switch (expr->opType)
+                               {
+                                       case OP_EXPR:
+                                               break;
+                                       case FUNC_EXPR:
+                                               break;
+                                       case OR_EXPR:
+                                               break;
+                                       case AND_EXPR:
+                                               break;
+                                       case NOT_EXPR:
+                                               break;
+                                       case DISTINCT_EXPR:
+                                               break;
+                                       case SUBPLAN_EXPR:
+                                               if (parent)
+                                               {
+                                                       SubLink *sublink = ((SubPlan *) expr->oper)->sublink;
+
+                                                       /*
+                                                        * Here we just add the SubPlan nodes to
+                                                        * parent->subPlan.  Later they will be expanded
+                                                        * to SubPlanState nodes.
+                                                        */
+                                                       parent->subPlan = lcons(expr->oper,
+                                                                                                       parent->subPlan);
+
+                                                       /* Must recurse into oper list too */
+                                                       Assert(IsA(sublink, SubLink));
+                                                       if (sublink->lefthand)
+                                                               elog(ERROR, "ExecInitExpr: sublink has not been transformed");
+                                                       ExecInitExpr((Node *) sublink->oper, parent);
+                                               }
+                                               else
+                                                       elog(ERROR, "ExecInitExpr: SubPlan not expected here");
+                                               break;
+                                       default:
+                                               elog(ERROR, "ExecInitExpr: unknown expression type %d",
+                                                        expr->opType);
+                                               break;
+                               }
+                               /* for all Expr node types, examine args list */
+                               ExecInitExpr((Node *) expr->args, parent);
+                       }
+                       break;
+               case T_FieldSelect:
+                       ExecInitExpr(((FieldSelect *) node)->arg, parent);
+                       break;
+               case T_RelabelType:
+                       ExecInitExpr(((RelabelType *) node)->arg, parent);
+                       break;
+               case T_CaseExpr:
+                       {
+                               CaseExpr   *caseexpr = (CaseExpr *) node;
+
+                               foreach(temp, caseexpr->args)
+                               {
+                                       CaseWhen   *when = (CaseWhen *) lfirst(temp);
+
+                                       Assert(IsA(when, CaseWhen));
+                                       ExecInitExpr(when->expr, parent);
+                                       ExecInitExpr(when->result, parent);
+                               }
+                               /* caseexpr->arg should be null, but we'll check it anyway */
+                               ExecInitExpr(caseexpr->arg, parent);
+                               ExecInitExpr(caseexpr->defresult, parent);
+                       }
+                       break;
+               case T_NullTest:
+                       ExecInitExpr(((NullTest *) node)->arg, parent);
+                       break;
+               case T_BooleanTest:
+                       ExecInitExpr(((BooleanTest *) node)->arg, parent);
+                       break;
+               case T_ConstraintTest:
+                       ExecInitExpr(((ConstraintTest *) node)->arg, parent);
+                       ExecInitExpr(((ConstraintTest *) node)->check_expr, parent);
+                       break;
+               case T_ConstraintTestValue:
+                       break;
+               case T_List:
+                       foreach(temp, (List *) node)
+                       {
+                               ExecInitExpr((Node *) lfirst(temp), parent);
+                       }
+                       break;
+               case T_TargetEntry:
+                       ExecInitExpr(((TargetEntry *) node)->expr, parent);
+                       break;
+               default:
+                       elog(ERROR, "ExecInitExpr: unknown expression type %d",
+                                nodeTag(node));
+                       break;
+       }
+
+       return node;
+}
+
+
 /* ----------------------------------------------------------------
  *                                      ExecQual / ExecTargetList / ExecProject
  * ----------------------------------------------------------------
index 9fd7c4f..6944e03 100644 (file)
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.21 2002/09/02 02:47:02 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.22 2002/12/05 15:50:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecScan(Scan *node,
+ExecScan(ScanState *node,
                 ExecScanAccessMtd accessMtd)   /* function returning a tuple */
 {
-       CommonScanState *scanstate;
        EState     *estate;
        ExprContext *econtext;
        List       *qual;
@@ -57,23 +56,22 @@ ExecScan(Scan *node,
        /*
         * Fetch data from node
         */
-       estate = node->plan.state;
-       scanstate = node->scanstate;
-       econtext = scanstate->cstate.cs_ExprContext;
-       qual = node->plan.qual;
+       estate = node->ps.state;
+       econtext = node->ps.ps_ExprContext;
+       qual = node->ps.qual;
 
        /*
         * Check to see if we're still projecting out tuples from a previous
         * scan tuple (because there is a function-returning-set in the
         * projection expressions).  If so, try to project another one.
         */
-       if (scanstate->cstate.cs_TupFromTlist)
+       if (node->ps.ps_TupFromTlist)
        {
-               resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
+               resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
                if (isDone == ExprMultipleResult)
                        return resultSlot;
                /* Done with that source tuple... */
-               scanstate->cstate.cs_TupFromTlist = false;
+               node->ps.ps_TupFromTlist = false;
        }
 
        /*
@@ -104,7 +102,7 @@ ExecScan(Scan *node,
                if (TupIsNull(slot))
                {
                        return ExecStoreTuple(NULL,
-                                                                 scanstate->cstate.cs_ProjInfo->pi_slot,
+                                                                 node->ps.ps_ProjInfo->pi_slot,
                                                                  InvalidBuffer,
                                                                  true);
                }
@@ -130,10 +128,10 @@ ExecScan(Scan *node,
                         * return it --- unless we find we can project no tuples from
                         * this scan tuple, in which case continue scan.
                         */
-                       resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
+                       resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
                        if (isDone != ExprEndResult)
                        {
-                               scanstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult);
+                               node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
                                return resultSlot;
                        }
                }
index 7b0df66..f5a6863 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.60 2002/09/28 20:00:19 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.61 2002/12/05 15:50:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -483,11 +483,11 @@ ExecSetSlotDescriptorIsNew(TupleTableSlot *slot,          /* slot to change */
  * ----------------
  */
 void
-ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
+ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
 {
        INIT_SLOT_DEFS;
        INIT_SLOT_ALLOC;
-       commonstate->cs_ResultTupleSlot = slot;
+       planstate->ps_ResultTupleSlot = slot;
 }
 
 /* ----------------
@@ -495,11 +495,11 @@ ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
  * ----------------
  */
 void
-ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate)
+ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
 {
        INIT_SLOT_DEFS;
        INIT_SLOT_ALLOC;
-       commonscanstate->css_ScanTupleSlot = slot;
+       scanstate->ss_ScanTupleSlot = slot;
 }
 
 /* ----------------
index 86440d1..0dd17b7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.90 2002/09/04 20:31:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.91 2002/12/05 15:50:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -142,7 +142,7 @@ DisplayTupleCount(FILE *statfp)
  * ----------------
  */
 void
-ExecAssignExprContext(EState *estate, CommonState *commonstate)
+ExecAssignExprContext(EState *estate, PlanState *planstate)
 {
        ExprContext *econtext = makeNode(ExprContext);
 
@@ -166,7 +166,7 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate)
        econtext->ecxt_aggnulls = NULL;
        econtext->ecxt_callbacks = NULL;
 
-       commonstate->cs_ExprContext = econtext;
+       planstate->ps_ExprContext = econtext;
 }
 
 /* ----------------
@@ -259,10 +259,10 @@ MakePerTupleExprContext(EState *estate)
  * ----------------
  */
 void
-ExecAssignResultType(CommonState *commonstate,
+ExecAssignResultType(PlanState *planstate,
                                         TupleDesc tupDesc, bool shouldFree)
 {
-       TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
+       TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
 
        ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
 }
@@ -272,15 +272,15 @@ ExecAssignResultType(CommonState *commonstate,
  * ----------------
  */
 void
-ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
+ExecAssignResultTypeFromOuterPlan(PlanState *planstate)
 {
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
        TupleDesc       tupDesc;
 
-       outerPlan = outerPlan(node);
+       outerPlan = outerPlanState(planstate);
        tupDesc = ExecGetTupType(outerPlan);
 
-       ExecAssignResultType(commonstate, tupDesc, false);
+       ExecAssignResultType(planstate, tupDesc, false);
 }
 
 /* ----------------
@@ -288,7 +288,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
  * ----------------
  */
 void
-ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
+ExecAssignResultTypeFromTL(PlanState *planstate)
 {
        ResultRelInfo *ri;
        bool            hasoid = false;
@@ -311,7 +311,7 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
         * each of the child plans of the topmost Append plan.  So, this is
         * ugly but it works, for now ...
         */
-       ri = node->state->es_result_relation_info;
+       ri = planstate->state->es_result_relation_info;
        if (ri != NULL)
        {
                Relation        rel = ri->ri_RelationDesc;
@@ -320,8 +320,13 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
                        hasoid = rel->rd_rel->relhasoids;
        }
 
-       tupDesc = ExecTypeFromTL(node->targetlist, hasoid);
-       ExecAssignResultType(commonstate, tupDesc, true);
+       /*
+        * XXX Some plan nodes don't bother to set up planstate->targetlist,
+        * so use the underlying plan's targetlist instead.  This will probably
+        * need to be fixed later.
+        */
+       tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
+       ExecAssignResultType(planstate, tupDesc, true);
 }
 
 /* ----------------
@@ -329,9 +334,9 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
  * ----------------
  */
 TupleDesc
-ExecGetResultType(CommonState *commonstate)
+ExecGetResultType(PlanState *planstate)
 {
-       TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
+       TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
 
        return slot->ttc_tupleDescriptor;
 }
@@ -342,23 +347,23 @@ ExecGetResultType(CommonState *commonstate)
  * ----------------
  */
 void
-ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
+ExecAssignProjectionInfo(PlanState *planstate)
 {
        ProjectionInfo *projInfo;
        List       *targetList;
        int                     len;
 
-       targetList = node->targetlist;
+       targetList = planstate->targetlist;
        len = ExecTargetListLength(targetList);
 
        projInfo = makeNode(ProjectionInfo);
        projInfo->pi_targetlist = targetList;
        projInfo->pi_len = len;
        projInfo->pi_tupValue = (len <= 0) ? NULL : (Datum *) palloc(sizeof(Datum) * len);
-       projInfo->pi_exprContext = commonstate->cs_ExprContext;
-       projInfo->pi_slot = commonstate->cs_ResultTupleSlot;
+       projInfo->pi_exprContext = planstate->ps_ExprContext;
+       projInfo->pi_slot = planstate->ps_ResultTupleSlot;
 
-       commonstate->cs_ProjInfo = projInfo;
+       planstate->ps_ProjInfo = projInfo;
 }
 
 
@@ -367,7 +372,7 @@ ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
  * ----------------
  */
 void
-ExecFreeProjectionInfo(CommonState *commonstate)
+ExecFreeProjectionInfo(PlanState *planstate)
 {
        ProjectionInfo *projInfo;
 
@@ -375,7 +380,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
         * get projection info.  if NULL then this node has none so we just
         * return.
         */
-       projInfo = commonstate->cs_ProjInfo;
+       projInfo = planstate->ps_ProjInfo;
        if (projInfo == NULL)
                return;
 
@@ -386,7 +391,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
                pfree(projInfo->pi_tupValue);
 
        pfree(projInfo);
-       commonstate->cs_ProjInfo = NULL;
+       planstate->ps_ProjInfo = NULL;
 }
 
 /* ----------------
@@ -394,7 +399,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
  * ----------------
  */
 void
-ExecFreeExprContext(CommonState *commonstate)
+ExecFreeExprContext(PlanState *planstate)
 {
        ExprContext *econtext;
 
@@ -402,7 +407,7 @@ ExecFreeExprContext(CommonState *commonstate)
         * get expression context.      if NULL then this node has none so we just
         * return.
         */
-       econtext = commonstate->cs_ExprContext;
+       econtext = planstate->ps_ExprContext;
        if (econtext == NULL)
                return;
 
@@ -416,7 +421,7 @@ ExecFreeExprContext(CommonState *commonstate)
         */
        MemoryContextDelete(econtext->ecxt_per_tuple_memory);
        pfree(econtext);
-       commonstate->cs_ExprContext = NULL;
+       planstate->ps_ExprContext = NULL;
 }
 
 /* ----------------------------------------------------------------
@@ -434,9 +439,9 @@ ExecFreeExprContext(CommonState *commonstate)
  * ----------------
  */
 TupleDesc
-ExecGetScanType(CommonScanState *csstate)
+ExecGetScanType(ScanState *scanstate)
 {
-       TupleTableSlot *slot = csstate->css_ScanTupleSlot;
+       TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
 
        return slot->ttc_tupleDescriptor;
 }
@@ -446,10 +451,10 @@ ExecGetScanType(CommonScanState *csstate)
  * ----------------
  */
 void
-ExecAssignScanType(CommonScanState *csstate,
+ExecAssignScanType(ScanState *scanstate,
                                   TupleDesc tupDesc, bool shouldFree)
 {
-       TupleTableSlot *slot = csstate->css_ScanTupleSlot;
+       TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
 
        ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
 }
@@ -459,15 +464,15 @@ ExecAssignScanType(CommonScanState *csstate,
  * ----------------
  */
 void
-ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate)
+ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
 {
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
        TupleDesc       tupDesc;
 
-       outerPlan = outerPlan(node);
+       outerPlan = outerPlanState(scanstate);
        tupDesc = ExecGetTupType(outerPlan);
 
-       ExecAssignScanType(csstate, tupDesc, false);
+       ExecAssignScanType(scanstate, tupDesc, false);
 }
 
 
@@ -718,7 +723,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
 }
 
 void
-SetChangedParamList(Plan *node, List *newchg)
+SetChangedParamList(PlanState *node, List *newchg)
 {
        List       *nl;
 
@@ -727,8 +732,8 @@ SetChangedParamList(Plan *node, List *newchg)
                int                     paramId = lfirsti(nl);
 
                /* if this node doesn't depend on a param ... */
-               if (!intMember(paramId, node->extParam) &&
-                       !intMember(paramId, node->locParam))
+               if (!intMember(paramId, node->plan->extParam) &&
+                       !intMember(paramId, node->plan->locParam))
                        continue;
                /* if this param is already in list of changed ones ... */
                if (intMember(paramId, node->chgParam))
index 71166d9..328aea5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.60 2002/11/13 00:39:47 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.61 2002/12/05 15:50:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,9 @@
 
 
 /*
- * We have an execution_state record for each query in a function.
+ * We have an execution_state record for each query in a function.  Each
+ * record contains a querytree and plantree for its query.  If the query
+ * is currently in F_EXEC_RUN state then there's a QueryDesc too.
  */
 typedef enum
 {
@@ -37,10 +39,11 @@ typedef enum
 
 typedef struct local_es
 {
-       QueryDesc  *qd;
-       EState     *estate;
        struct local_es *next;
        ExecStatus      status;
+       Query      *query;
+       Plan       *plan;
+       QueryDesc  *qd;                         /* null unless status == RUN */
 } execution_state;
 
 #define LAST_POSTQUEL_COMMAND(es) ((es)->next == (execution_state *) NULL)
@@ -62,6 +65,8 @@ typedef struct
                                                                 * we end execution of the function and
                                                                 * free stuff */
 
+       ParamListInfo paramLI;          /* Param list representing current args */
+
        /* head of linked list of execution_state records */
        execution_state *func_state;
 } SQLFunctionCache;
@@ -73,10 +78,11 @@ typedef SQLFunctionCache *SQLFunctionCachePtr;
 static execution_state *init_execution_state(char *src,
                                         Oid *argOidVect, int nargs);
 static void init_sql_fcache(FmgrInfo *finfo);
-static void postquel_start(execution_state *es);
+static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
 static TupleTableSlot *postquel_getnext(execution_state *es);
 static void postquel_end(execution_state *es);
-static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo);
+static void postquel_sub_params(SQLFunctionCachePtr fcache,
+                                                               FunctionCallInfo fcinfo);
 static Datum postquel_execute(execution_state *es,
                                 FunctionCallInfo fcinfo,
                                 SQLFunctionCachePtr fcache);
@@ -101,7 +107,6 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
                Query      *queryTree = lfirst(qtl_item);
                Plan       *planTree;
                execution_state *newes;
-               EState     *estate;
 
                planTree = pg_plan_query(queryTree);
 
@@ -113,29 +118,9 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
 
                newes->next = NULL;
                newes->status = F_EXEC_START;
-               newes->qd = CreateQueryDesc(queryTree, planTree, None, NULL);
-               newes->estate = estate = CreateExecutorState();
-
-               if (nargs > 0)
-               {
-                       int                     i;
-                       ParamListInfo paramLI;
-
-                       paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
-
-                       estate->es_param_list_info = paramLI;
-
-                       for (i = 0; i < nargs; paramLI++, i++)
-                       {
-                               paramLI->kind = PARAM_NUM;
-                               paramLI->id = i + 1;
-                               paramLI->isnull = false;
-                               paramLI->value = (Datum) NULL;
-                       }
-                       paramLI->kind = PARAM_INVALID;
-               }
-               else
-                       estate->es_param_list_info = (ParamListInfo) NULL;
+               newes->query = queryTree;
+               newes->plan = planTree;
+               newes->qd = NULL;
 
                preves = newes;
        }
@@ -219,6 +204,10 @@ init_sql_fcache(FmgrInfo *finfo)
        else
                fcache->funcSlot = NULL;
 
+       /*
+        * Parse and plan the queries.  We need the argument info to pass
+        * to the parser.
+        */
        nargs = procedureStruct->pronargs;
 
        if (nargs > 0)
@@ -252,15 +241,18 @@ init_sql_fcache(FmgrInfo *finfo)
 
 
 static void
-postquel_start(execution_state *es)
+postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
 {
-       /*
-        * Do nothing for utility commands. (create, destroy...)  DZ -
-        * 30-8-1996
-        */
-       if (es->qd->operation == CMD_UTILITY)
-               return;
-       ExecutorStart(es->qd, es->estate);
+       Assert(es->qd == NULL);
+       es->qd = CreateQueryDesc(es->query, es->plan,
+                                                        None, NULL,
+                                                        fcache->paramLI, false);
+
+       /* Utility commands don't need Executor. */
+       if (es->qd->operation != CMD_UTILITY)
+               ExecutorStart(es->qd);
+
+       es->status = F_EXEC_RUN;
 }
 
 static TupleTableSlot *
@@ -282,40 +274,52 @@ postquel_getnext(execution_state *es)
        /* If it's not the last command, just run it to completion */
        count = (LAST_POSTQUEL_COMMAND(es)) ? 1L : 0L;
 
-       return ExecutorRun(es->qd, es->estate, ForwardScanDirection, count);
+       return ExecutorRun(es->qd, ForwardScanDirection, count);
 }
 
 static void
 postquel_end(execution_state *es)
 {
-       /*
-        * Do nothing for utility commands. (create, destroy...)  DZ -
-        * 30-8-1996
-        */
-       if (es->qd->operation == CMD_UTILITY)
-               return;
-       ExecutorEnd(es->qd, es->estate);
+       /* Utility commands don't need Executor. */
+       if (es->qd->operation != CMD_UTILITY)
+               ExecutorEnd(es->qd);
+
+       pfree(es->qd);
+       es->qd = NULL;
+
+       es->status = F_EXEC_DONE;
 }
 
+/* Build ParamListInfo array representing current arguments */
 static void
-postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo)
+postquel_sub_params(SQLFunctionCachePtr fcache,
+                                       FunctionCallInfo fcinfo)
 {
-       EState     *estate;
        ParamListInfo paramLI;
+       int                     nargs = fcinfo->nargs;
 
-       estate = es->estate;
-       paramLI = estate->es_param_list_info;
-
-       while (paramLI->kind != PARAM_INVALID)
+       if (nargs > 0)
        {
-               if (paramLI->kind == PARAM_NUM)
+               int                     i;
+
+               paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
+
+               for (i = 0; i < nargs; i++)
                {
-                       Assert(paramLI->id <= fcinfo->nargs);
-                       paramLI->value = fcinfo->arg[paramLI->id - 1];
-                       paramLI->isnull = fcinfo->argnull[paramLI->id - 1];
+                       paramLI[i].kind = PARAM_NUM;
+                       paramLI[i].id = i + 1;
+                       paramLI[i].value = fcinfo->arg[i];
+                       paramLI[i].isnull = fcinfo->argnull[i];
                }
-               paramLI++;
+               paramLI[nargs].kind = PARAM_INVALID;
        }
+       else
+               paramLI = (ParamListInfo) NULL;
+
+       if (fcache->paramLI)
+               pfree(fcache->paramLI);
+
+       fcache->paramLI = paramLI;
 }
 
 static TupleTableSlot *
@@ -359,27 +363,14 @@ postquel_execute(execution_state *es,
        TupleTableSlot *slot;
        Datum           value;
 
-       /*
-        * It's more right place to do it (before
-        * postquel_start->ExecutorStart). Now
-        * ExecutorStart->ExecInitIndexScan->ExecEvalParam works ok. (But
-        * note: I HOPE we can do it here). - vadim 01/22/97
-        */
-       if (fcinfo->nargs > 0)
-               postquel_sub_params(es, fcinfo);
-
        if (es->status == F_EXEC_START)
-       {
-               postquel_start(es);
-               es->status = F_EXEC_RUN;
-       }
+               postquel_start(es, fcache);
 
        slot = postquel_getnext(es);
 
        if (TupIsNull(slot))
        {
                postquel_end(es);
-               es->status = F_EXEC_DONE;
                fcinfo->isnull = true;
 
                /*
@@ -438,10 +429,7 @@ postquel_execute(execution_state *es,
                 * execution now.
                 */
                if (!fcinfo->flinfo->fn_retset)
-               {
                        postquel_end(es);
-                       es->status = F_EXEC_DONE;
-               }
 
                return value;
        }
@@ -471,7 +459,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
        oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
 
        /*
-        * Initialize fcache and execution state if first time through.
+        * Initialize fcache (build plans) if first time through.
         */
        fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
        if (fcache == NULL)
@@ -482,6 +470,13 @@ fmgr_sql(PG_FUNCTION_ARGS)
        es = fcache->func_state;
 
        /*
+        * Convert params to appropriate format if starting a fresh execution.
+        * (If continuing execution, we can re-use prior params.)
+        */
+       if (es && es->status == F_EXEC_START)
+               postquel_sub_params(fcache, fcinfo);
+
+       /*
         * Find first unfinished query in function.
         */
        while (es && es->status == F_EXEC_DONE)
@@ -506,7 +501,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
        if (es == (execution_state *) NULL)
        {
                /*
-                * Reset the execution states to start over again
+                * Reset the execution states to start over again on next call.
                 */
                es = fcache->func_state;
                while (es)
index 82e9f48..bdbe61c 100644 (file)
@@ -45,7 +45,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.97 2002/11/29 21:39:11 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.98 2002/12/05 15:50:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -212,11 +212,12 @@ static void finalize_aggregate(AggState *aggstate,
                                                           AggStatePerAgg peraggstate,
                                                           AggStatePerGroup pergroupstate,
                                                           Datum *resultVal, bool *resultIsNull);
-static void build_hash_table(Agg *node);
-static AggHashEntry lookup_hash_entry(Agg *node, TupleTableSlot *slot);
-static TupleTableSlot *agg_retrieve_direct(Agg *node);
-static void agg_fill_hash_table(Agg *node);
-static TupleTableSlot *agg_retrieve_hash_table(Agg *node);
+static void build_hash_table(AggState *aggstate);
+static AggHashEntry lookup_hash_entry(AggState *aggstate,
+                                                                         TupleTableSlot *slot);
+static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
+static void agg_fill_hash_table(AggState *aggstate);
+static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
 
 
@@ -521,7 +522,7 @@ finalize_aggregate(AggState *aggstate,
 {
        MemoryContext oldContext;
 
-       oldContext = MemoryContextSwitchTo(aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory);
+       oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
 
        /*
         * Apply the agg's finalfn if one is provided, else return transValue.
@@ -572,9 +573,9 @@ finalize_aggregate(AggState *aggstate,
  * The hash table always lives in the aggcontext memory context.
  */
 static void
-build_hash_table(Agg *node)
+build_hash_table(AggState *aggstate)
 {
-       AggState   *aggstate = node->aggstate;
+       Agg                        *node = (Agg *) aggstate->ss.ps.plan;
        AggHashTable    hashtable;
        Size                    tabsize;
 
@@ -596,9 +597,9 @@ build_hash_table(Agg *node)
  * When called, CurrentMemoryContext should be the per-query context.
  */
 static AggHashEntry
-lookup_hash_entry(Agg *node, TupleTableSlot *slot)
+lookup_hash_entry(AggState *aggstate, TupleTableSlot *slot)
 {
-       AggState   *aggstate = node->aggstate;
+       Agg                *node = (Agg *) aggstate->ss.ps.plan;
        AggHashTable hashtable = aggstate->hashtable;
        MemoryContext   tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
        HeapTuple       tuple = slot->val;
@@ -684,16 +685,14 @@ lookup_hash_entry(Agg *node, TupleTableSlot *slot)
  *       the result tuple.
  */
 TupleTableSlot *
-ExecAgg(Agg *node)
+ExecAgg(AggState *node)
 {
-       AggState   *aggstate = node->aggstate;
-
-       if (aggstate->agg_done)
+       if (node->agg_done)
                return NULL;
 
-       if (node->aggstrategy == AGG_HASHED)
+       if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
        {
-               if (!aggstate->table_filled)
+               if (!node->table_filled)
                        agg_fill_hash_table(node);
                return agg_retrieve_hash_table(node);
        }
@@ -707,10 +706,10 @@ ExecAgg(Agg *node)
  * ExecAgg for non-hashed case
  */
 static TupleTableSlot *
-agg_retrieve_direct(Agg *node)
+agg_retrieve_direct(AggState *aggstate)
 {
-       AggState   *aggstate;
-       Plan       *outerPlan;
+       Agg                *node = (Agg *) aggstate->ss.ps.plan;
+       PlanState  *outerPlan;
        ExprContext *econtext;
        ExprContext *tmpcontext;
        ProjectionInfo *projInfo;
@@ -726,22 +725,21 @@ agg_retrieve_direct(Agg *node)
        /*
         * get state info from node
         */
-       aggstate = node->aggstate;
-       outerPlan = outerPlan(node);
+       outerPlan = outerPlanState(aggstate);
        /* econtext is the per-output-tuple expression context */
-       econtext = aggstate->csstate.cstate.cs_ExprContext;
+       econtext = aggstate->ss.ps.ps_ExprContext;
        aggvalues = econtext->ecxt_aggvalues;
        aggnulls = econtext->ecxt_aggnulls;
        /* tmpcontext is the per-input-tuple expression context */
        tmpcontext = aggstate->tmpcontext;
-       projInfo = aggstate->csstate.cstate.cs_ProjInfo;
+       projInfo = aggstate->ss.ps.ps_ProjInfo;
        peragg = aggstate->peragg;
        pergroup = aggstate->pergroup;
-       firstSlot = aggstate->csstate.css_ScanTupleSlot;
+       firstSlot = aggstate->ss.ss_ScanTupleSlot;
 
        /*
         * We loop retrieving groups until we find one matching
-        * node->plan.qual
+        * aggstate->ss.ps.qual
         */
        do
        {
@@ -754,7 +752,7 @@ agg_retrieve_direct(Agg *node)
                 */
                if (aggstate->grp_firstTuple == NULL)
                {
-                       outerslot = ExecProcNode(outerPlan, (Plan *) node);
+                       outerslot = ExecProcNode(outerPlan);
                        if (!TupIsNull(outerslot))
                        {
                                /*
@@ -810,7 +808,7 @@ agg_retrieve_direct(Agg *node)
                                /* Reset per-input-tuple context after each tuple */
                                ResetExprContext(tmpcontext);
 
-                               outerslot = ExecProcNode(outerPlan, (Plan *) node);
+                               outerslot = ExecProcNode(outerPlan);
                                if (TupIsNull(outerslot))
                                {
                                        /* no more outer-plan tuples available */
@@ -917,7 +915,7 @@ agg_retrieve_direct(Agg *node)
                 * Otherwise, return the tuple.
                 */
        }
-       while (!ExecQual(node->plan.qual, econtext, false));
+       while (!ExecQual(aggstate->ss.ps.qual, econtext, false));
 
        return resultSlot;
 }
@@ -926,10 +924,9 @@ agg_retrieve_direct(Agg *node)
  * ExecAgg for hashed case: phase 1, read input and build hash table
  */
 static void
-agg_fill_hash_table(Agg *node)
+agg_fill_hash_table(AggState *aggstate)
 {
-       AggState   *aggstate;
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
        ExprContext *tmpcontext;
        AggHashEntry    entry;
        TupleTableSlot *outerslot;
@@ -937,8 +934,7 @@ agg_fill_hash_table(Agg *node)
        /*
         * get state info from node
         */
-       aggstate = node->aggstate;
-       outerPlan = outerPlan(node);
+       outerPlan = outerPlanState(aggstate);
        /* tmpcontext is the per-input-tuple expression context */
        tmpcontext = aggstate->tmpcontext;
 
@@ -948,14 +944,14 @@ agg_fill_hash_table(Agg *node)
         */
        for (;;)
        {
-               outerslot = ExecProcNode(outerPlan, (Plan *) node);
+               outerslot = ExecProcNode(outerPlan);
                if (TupIsNull(outerslot))
                        break;
                /* set up for advance_aggregates call */
                tmpcontext->ecxt_scantuple = outerslot;
 
                /* Find or build hashtable entry for this tuple's group */
-               entry = lookup_hash_entry(node, outerslot);
+               entry = lookup_hash_entry(aggstate, outerslot);
 
                /* Advance the aggregates */
                advance_aggregates(aggstate, entry->pergroup);
@@ -974,9 +970,8 @@ agg_fill_hash_table(Agg *node)
  * ExecAgg for hashed case: phase 2, retrieving groups from hash table
  */
 static TupleTableSlot *
-agg_retrieve_hash_table(Agg *node)
+agg_retrieve_hash_table(AggState *aggstate)
 {
-       AggState   *aggstate;
        ExprContext *econtext;
        ProjectionInfo *projInfo;
        Datum      *aggvalues;
@@ -992,19 +987,18 @@ agg_retrieve_hash_table(Agg *node)
        /*
         * get state info from node
         */
-       aggstate = node->aggstate;
        /* econtext is the per-output-tuple expression context */
-       econtext = aggstate->csstate.cstate.cs_ExprContext;
+       econtext = aggstate->ss.ps.ps_ExprContext;
        aggvalues = econtext->ecxt_aggvalues;
        aggnulls = econtext->ecxt_aggnulls;
-       projInfo = aggstate->csstate.cstate.cs_ProjInfo;
+       projInfo = aggstate->ss.ps.ps_ProjInfo;
        peragg = aggstate->peragg;
        hashtable = aggstate->hashtable;
-       firstSlot = aggstate->csstate.css_ScanTupleSlot;
+       firstSlot = aggstate->ss.ss_ScanTupleSlot;
 
        /*
-        * We loop retrieving groups until we find one matching
-        * node->plan.qual
+        * We loop retrieving groups until we find one satisfying
+        * aggstate->ss.ps.qual
         */
        do
        {
@@ -1071,7 +1065,7 @@ agg_retrieve_hash_table(Agg *node)
                 * Otherwise, return the tuple.
                 */
        }
-       while (!ExecQual(node->plan.qual, econtext, false));
+       while (!ExecQual(aggstate->ss.ps.qual, econtext, false));
 
        return resultSlot;
 }
@@ -1083,8 +1077,8 @@ agg_retrieve_hash_table(Agg *node)
  *     planner and initializes its outer subtree
  * -----------------
  */
-bool
-ExecInitAgg(Agg *node, EState *estate, Plan *parent)
+AggState *
+ExecInitAgg(Agg *node, EState *estate)
 {
        AggState   *aggstate;
        AggStatePerAgg peragg;
@@ -1095,15 +1089,14 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
        List       *alist;
 
        /*
-        * assign the node's execution state
-        */
-       node->plan.state = estate;
-
-       /*
         * create state structure
         */
        aggstate = makeNode(AggState);
-       node->aggstate = aggstate;
+       aggstate->ss.ps.plan = (Plan *) node;
+       aggstate->ss.ps.state = estate;
+
+       aggstate->aggs = NIL;
+       aggstate->numaggs = 0;
        aggstate->eqfunctions = NULL;
        aggstate->peragg = NULL;
        aggstate->agg_done = false;
@@ -1112,37 +1105,13 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
        aggstate->hashtable = NULL;
 
        /*
-        * find aggregates in targetlist and quals
-        *
-        * Note: pull_agg_clauses also checks that no aggs contain other agg
-        * calls in their arguments.  This would make no sense under SQL
-        * semantics anyway (and it's forbidden by the spec).  Because that is
-        * true, we don't need to worry about evaluating the aggs in any
-        * particular order.
-        */
-       aggstate->aggs = nconc(pull_agg_clause((Node *) node->plan.targetlist),
-                                                  pull_agg_clause((Node *) node->plan.qual));
-       aggstate->numaggs = numaggs = length(aggstate->aggs);
-       if (numaggs <= 0)
-       {
-               /*
-                * This is not an error condition: we might be using the Agg node just
-                * to do hash-based grouping.  Even in the regular case,
-                * constant-expression simplification could optimize away all of the
-                * Aggrefs in the targetlist and qual.  So keep going, but force local
-                * copy of numaggs positive so that palloc()s below don't choke.
-                */
-               numaggs = 1;
-       }
-
-       /*
         * Create expression contexts.  We need two, one for per-input-tuple
         * processing and one for per-output-tuple processing.  We cheat a little
         * by using ExecAssignExprContext() to build both.
         */
-       ExecAssignExprContext(estate, &aggstate->csstate.cstate);
-       aggstate->tmpcontext = aggstate->csstate.cstate.cs_ExprContext;
-       ExecAssignExprContext(estate, &aggstate->csstate.cstate);
+       ExecAssignExprContext(estate, &aggstate->ss.ps);
+       aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
+       ExecAssignExprContext(estate, &aggstate->ss.ps);
 
        /*
         * We also need a long-lived memory context for holding hashtable
@@ -1163,14 +1132,64 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
        /*
         * tuple table initialization
         */
-       ExecInitScanTupleSlot(estate, &aggstate->csstate);
-       ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate);
+       ExecInitScanTupleSlot(estate, &aggstate->ss);
+       ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
+
+       /*
+        * initialize child expressions
+        *
+        * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
+        * contain other agg calls in their arguments.  This would make no sense
+        * under SQL semantics anyway (and it's forbidden by the spec).  Because
+        * that is true, we don't need to worry about evaluating the aggs in any
+        * particular order.
+        */
+       aggstate->ss.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->plan.targetlist,
+                                        (PlanState *) aggstate);
+       aggstate->ss.ps.qual = (List *)
+               ExecInitExpr((Node *) node->plan.qual,
+                                        (PlanState *) aggstate);
+
+       /*
+        * initialize child nodes
+        */
+       outerPlan = outerPlan(node);
+       outerPlanState(aggstate) = ExecInitNode(outerPlan, estate);
+
+       /*
+        * initialize source tuple type.
+        */
+       ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
+
+       /*
+        * Initialize result tuple type and projection info.
+        */
+       ExecAssignResultTypeFromTL(&aggstate->ss.ps);
+       ExecAssignProjectionInfo(&aggstate->ss.ps);
+
+       /*
+        * get the count of aggregates in targetlist and quals
+        */
+       numaggs = aggstate->numaggs;
+       Assert(numaggs == length(aggstate->aggs));
+       if (numaggs <= 0)
+       {
+               /*
+                * This is not an error condition: we might be using the Agg node just
+                * to do hash-based grouping.  Even in the regular case,
+                * constant-expression simplification could optimize away all of the
+                * Aggrefs in the targetlist and qual.  So keep going, but force local
+                * copy of numaggs positive so that palloc()s below don't choke.
+                */
+               numaggs = 1;
+       }
 
        /*
         * Set up aggregate-result storage in the output expr context, and also
         * allocate my private per-agg working storage
         */
-       econtext = aggstate->csstate.cstate.cs_ExprContext;
+       econtext = aggstate->ss.ps.ps_ExprContext;
        econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
        econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
 
@@ -1179,7 +1198,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
 
        if (node->aggstrategy == AGG_HASHED)
        {
-               build_hash_table(node);
+               build_hash_table(aggstate);
                aggstate->table_filled = false;
        }
        else
@@ -1191,29 +1210,12 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
        }
 
        /*
-        * initialize child nodes
-        */
-       outerPlan = outerPlan(node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
-
-       /*
-        * initialize source tuple type.
-        */
-       ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate);
-
-       /*
-        * Initialize result tuple type and projection info.
-        */
-       ExecAssignResultTypeFromTL((Plan *) node, &aggstate->csstate.cstate);
-       ExecAssignProjectionInfo((Plan *) node, &aggstate->csstate.cstate);
-
-       /*
         * If we are grouping, precompute fmgr lookup data for inner loop
         */
        if (node->numCols > 0)
        {
                aggstate->eqfunctions =
-                       execTuplesMatchPrepare(ExecGetScanType(&aggstate->csstate),
+                       execTuplesMatchPrepare(ExecGetScanType(&aggstate->ss),
                                                                   node->numCols,
                                                                   node->grpColIdx);
        }
@@ -1330,7 +1332,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
                ReleaseSysCache(aggTuple);
        }
 
-       return TRUE;
+       return aggstate;
 }
 
 static Datum
@@ -1372,84 +1374,82 @@ ExecCountSlotsAgg(Agg *node)
 }
 
 void
-ExecEndAgg(Agg *node)
+ExecEndAgg(AggState *node)
 {
-       AggState   *aggstate = node->aggstate;
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
        int                     aggno;
 
        /* Make sure we have closed any open tuplesorts */
-       for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+       for (aggno = 0; aggno < node->numaggs; aggno++)
        {
-               AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
+               AggStatePerAgg peraggstate = &node->peragg[aggno];
 
                if (peraggstate->sortstate)
                        tuplesort_end(peraggstate->sortstate);
        }
 
-       ExecFreeProjectionInfo(&aggstate->csstate.cstate);
+       ExecFreeProjectionInfo(&node->ss.ps);
 
        /*
         * Free both the expr contexts.
         */
-       ExecFreeExprContext(&aggstate->csstate.cstate);
-       aggstate->csstate.cstate.cs_ExprContext = aggstate->tmpcontext;
-       ExecFreeExprContext(&aggstate->csstate.cstate);
+       ExecFreeExprContext(&node->ss.ps);
+       node->ss.ps.ps_ExprContext = node->tmpcontext;
+       ExecFreeExprContext(&node->ss.ps);
 
-       MemoryContextDelete(aggstate->aggcontext);
+       MemoryContextDelete(node->aggcontext);
 
-       outerPlan = outerPlan(node);
-       ExecEndNode(outerPlan, (Plan *) node);
+       outerPlan = outerPlanState(node);
+       ExecEndNode(outerPlan);
 
        /* clean up tuple table */
-       ExecClearTuple(aggstate->csstate.css_ScanTupleSlot);
-       if (aggstate->grp_firstTuple != NULL)
+       ExecClearTuple(node->ss.ss_ScanTupleSlot);
+       if (node->grp_firstTuple != NULL)
        {
-               heap_freetuple(aggstate->grp_firstTuple);
-               aggstate->grp_firstTuple = NULL;
+               heap_freetuple(node->grp_firstTuple);
+               node->grp_firstTuple = NULL;
        }
 }
 
 void
-ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
 {
-       AggState   *aggstate = node->aggstate;
-       ExprContext *econtext = aggstate->csstate.cstate.cs_ExprContext;
+       ExprContext *econtext = node->ss.ps.ps_ExprContext;
        int                     aggno;
 
        /* Make sure we have closed any open tuplesorts */
-       for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+       for (aggno = 0; aggno < node->numaggs; aggno++)
        {
-               AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
+               AggStatePerAgg peraggstate = &node->peragg[aggno];
 
                if (peraggstate->sortstate)
                        tuplesort_end(peraggstate->sortstate);
                peraggstate->sortstate = NULL;
        }
 
-       aggstate->agg_done = false;
-       if (aggstate->grp_firstTuple != NULL)
+       node->agg_done = false;
+       if (node->grp_firstTuple != NULL)
        {
-               heap_freetuple(aggstate->grp_firstTuple);
-               aggstate->grp_firstTuple = NULL;
+               heap_freetuple(node->grp_firstTuple);
+               node->grp_firstTuple = NULL;
        }
-       MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * aggstate->numaggs);
-       MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * aggstate->numaggs);
+       MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
+       MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
 
-       MemoryContextReset(aggstate->aggcontext);
+       MemoryContextReset(node->aggcontext);
 
-       if (node->aggstrategy == AGG_HASHED)
+       if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
        {
                build_hash_table(node);
-               aggstate->table_filled = false;
+               node->table_filled = false;
        }
 
        /*
         * if chgParam of subnode is not null then plan will be re-scanned by
         * first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree->chgParam == NIL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 }
 
 /*
index 9d0e564..bcb50fb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.50 2002/11/13 00:39:47 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.51 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "executor/nodeAppend.h"
 #include "parser/parsetree.h"
 
-static bool exec_append_initialize_next(Append *node);
+static bool exec_append_initialize_next(AppendState *appendstate);
 
 
 /* ----------------------------------------------------------------
  *             exec_append_initialize_next
  *
- *             Sets up the append node state (i.e. the append state node)
- *             for the "next" scan.
+ *             Sets up the append state node for the "next" scan.
  *
  *             Returns t iff there is a "next" scan to process.
  * ----------------------------------------------------------------
  */
 static bool
-exec_append_initialize_next(Append *node)
+exec_append_initialize_next(AppendState *appendstate)
 {
        EState     *estate;
-       AppendState *appendstate;
        int                     whichplan;
 
        /*
         * get information from the append node
         */
-       estate = node->plan.state;
-       appendstate = node->appendstate;
+       estate = appendstate->ps.state;
        whichplan = appendstate->as_whichplan;
 
        if (whichplan < appendstate->as_firstplan)
@@ -116,7 +113,7 @@ exec_append_initialize_next(Append *node)
                 * If we are controlling the target relation, select the proper
                 * active ResultRelInfo and junk filter for this target.
                 */
-               if (node->isTarget)
+               if (((Append *) appendstate->ps.plan)->isTarget)
                {
                        Assert(whichplan < estate->es_num_result_relations);
                        estate->es_result_relation_info =
@@ -132,9 +129,7 @@ exec_append_initialize_next(Append *node)
 /* ----------------------------------------------------------------
  *             ExecInitAppend
  *
- *             Begins all of the subscans of the append node, storing the
- *             scan structures in the 'initialized' vector of the append-state
- *             structure.
+ *             Begin all of the subscans of the append node.
  *
  *        (This is potentially wasteful, since the entire result of the
  *             append node may not be scanned, but this way all of the
@@ -146,36 +141,31 @@ exec_append_initialize_next(Append *node)
  *             subplan that corresponds to the target relation being checked.
  * ----------------------------------------------------------------
  */
-bool
-ExecInitAppend(Append *node, EState *estate, Plan *parent)
+AppendState *
+ExecInitAppend(Append *node, EState *estate)
 {
-       AppendState *appendstate;
+       AppendState *appendstate = makeNode(AppendState);
+       PlanState **appendplanstates;
        int                     nplans;
-       List       *appendplans;
-       bool       *initialized;
        int                     i;
        Plan       *initNode;
 
        CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
 
        /*
-        * assign execution state to node and get information for append state
+        * Set up empty vector of subplan states
         */
-       node->plan.state = estate;
+       nplans = length(node->appendplans);
 
-       appendplans = node->appendplans;
-       nplans = length(appendplans);
-
-       initialized = (bool *) palloc0(nplans * sizeof(bool));
+       appendplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
 
        /*
         * create new AppendState for our append node
         */
-       appendstate = makeNode(AppendState);
+       appendstate->ps.plan = (Plan *) node;
+       appendstate->ps.state = estate;
+       appendstate->appendplans = appendplanstates;
        appendstate->as_nplans = nplans;
-       appendstate->as_initialized = initialized;
-
-       node->appendstate = appendstate;
 
        /*
         * Do we want to scan just one subplan?  (Special case for
@@ -212,36 +202,36 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
         * append nodes still have Result slots, which hold pointers to
         * tuples, so we have to initialize them.
         */
-       ExecInitResultTupleSlot(estate, &appendstate->cstate);
+       ExecInitResultTupleSlot(estate, &appendstate->ps);
 
        /*
         * call ExecInitNode on each of the plans to be executed and save the
-        * results into the array "initialized".  Note we *must* set
+        * results into the array "appendplans".  Note we *must* set
         * estate->es_result_relation_info correctly while we initialize each
         * sub-plan; ExecAssignResultTypeFromTL depends on that!
         */
        for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++)
        {
                appendstate->as_whichplan = i;
-               exec_append_initialize_next(node);
+               exec_append_initialize_next(appendstate);
 
-               initNode = (Plan *) nth(i, appendplans);
-               initialized[i] = ExecInitNode(initNode, estate, (Plan *) node);
+               initNode = (Plan *) nth(i, node->appendplans);
+               appendplanstates[i] = ExecInitNode(initNode, estate);
        }
 
        /*
         * initialize tuple type
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &appendstate->cstate);
-       appendstate->cstate.cs_ProjInfo = NULL;
+       ExecAssignResultTypeFromTL(&appendstate->ps);
+       appendstate->ps.ps_ProjInfo = NULL;
 
        /*
         * return the result from the first subplan's initialization
         */
        appendstate->as_whichplan = appendstate->as_firstplan;
-       exec_append_initialize_next(node);
+       exec_append_initialize_next(appendstate);
 
-       return TRUE;
+       return appendstate;
 }
 
 int
@@ -264,13 +254,11 @@ ExecCountSlotsAppend(Append *node)
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecProcAppend(Append *node)
+ExecProcAppend(AppendState *node)
 {
        EState     *estate;
-       AppendState *appendstate;
        int                     whichplan;
-       List       *appendplans;
-       Plan       *subnode;
+       PlanState  *subnode;
        TupleTableSlot *result;
        TupleTableSlot *result_slot;
        ScanDirection direction;
@@ -278,25 +266,20 @@ ExecProcAppend(Append *node)
        /*
         * get information from the node
         */
-       appendstate = node->appendstate;
-       estate = node->plan.state;
+       estate = node->ps.state;
        direction = estate->es_direction;
-       appendplans = node->appendplans;
-       whichplan = appendstate->as_whichplan;
-       result_slot = appendstate->cstate.cs_ResultTupleSlot;
+       whichplan = node->as_whichplan;
+       result_slot = node->ps.ps_ResultTupleSlot;
 
        /*
         * figure out which subplan we are currently processing
         */
-       subnode = (Plan *) nth(whichplan, appendplans);
-
-       if (subnode == NULL)
-               elog(DEBUG1, "ExecProcAppend: subnode is NULL");
+       subnode = node->appendplans[whichplan];
 
        /*
         * get a tuple from the subplan
         */
-       result = ExecProcNode(subnode, (Plan *) node);
+       result = ExecProcNode(subnode);
 
        if (!TupIsNull(result))
        {
@@ -316,9 +299,9 @@ ExecProcAppend(Append *node)
                 * try processing again (recursively)
                 */
                if (ScanDirectionIsForward(direction))
-                       appendstate->as_whichplan++;
+                       node->as_whichplan++;
                else
-                       appendstate->as_whichplan--;
+                       node->as_whichplan--;
 
                /*
                 * return something from next node or an empty slot if all of our
@@ -343,65 +326,56 @@ ExecProcAppend(Append *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndAppend(Append *node)
+ExecEndAppend(AppendState *node)
 {
-       EState     *estate;
-       AppendState *appendstate;
+       PlanState **appendplans;
        int                     nplans;
-       List       *appendplans;
-       bool       *initialized;
        int                     i;
 
        /*
         * get information from the node
         */
-       appendstate = node->appendstate;
-       estate = node->plan.state;
        appendplans = node->appendplans;
-       nplans = appendstate->as_nplans;
-       initialized = appendstate->as_initialized;
+       nplans = node->as_nplans;
 
        /*
-        * shut down each of the subscans
+        * shut down each of the subscans (that we've initialized)
         */
        for (i = 0; i < nplans; i++)
        {
-               if (initialized[i])
-                       ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node);
+               if (appendplans[i])
+                       ExecEndNode(appendplans[i]);
        }
 }
 
 void
-ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanAppend(AppendState *node, ExprContext *exprCtxt)
 {
-       AppendState *appendstate = node->appendstate;
        int                     i;
 
-       for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++)
+       for (i = node->as_firstplan; i <= node->as_lastplan; i++)
        {
-               Plan       *subnode;
-
-               subnode = (Plan *) nth(i, node->appendplans);
+               PlanState *subnode = node->appendplans[i];
 
                /*
                 * ExecReScan doesn't know about my subplans, so I have to do
                 * changed-parameter signaling myself.
                 */
-               if (node->plan.chgParam != NULL)
-                       SetChangedParamList(subnode, node->plan.chgParam);
+               if (node->ps.chgParam != NIL)
+                       SetChangedParamList(subnode, node->ps.chgParam);
 
                /*
                 * if chgParam of subnode is not null then plan will be re-scanned
                 * by first ExecProcNode.
                 */
-               if (subnode->chgParam == NULL)
+               if (subnode->chgParam == NIL)
                {
                        /* make sure estate is correct for this subnode (needed??) */
-                       appendstate->as_whichplan = i;
+                       node->as_whichplan = i;
                        exec_append_initialize_next(node);
-                       ExecReScan(subnode, exprCtxt, (Plan *) node);
+                       ExecReScan(subnode, exprCtxt);
                }
        }
-       appendstate->as_whichplan = appendstate->as_firstplan;
+       node->as_whichplan = node->as_firstplan;
        exec_append_initialize_next(node);
 }
index 97da70b..f6df416 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.13 2002/12/01 20:27:32 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,7 +34,7 @@
 #include "utils/lsyscache.h"
 
 
-static TupleTableSlot *FunctionNext(FunctionScan *node);
+static TupleTableSlot *FunctionNext(FunctionScanState *node);
 static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2);
 
 /* ----------------------------------------------------------------
@@ -48,24 +48,22 @@ static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2);
  * ----------------------------------------------------------------
  */
 static TupleTableSlot *
-FunctionNext(FunctionScan *node)
+FunctionNext(FunctionScanState *node)
 {
        TupleTableSlot *slot;
        EState     *estate;
        ScanDirection direction;
        Tuplestorestate *tuplestorestate;
-       FunctionScanState *scanstate;
        bool            should_free;
        HeapTuple       heapTuple;
 
        /*
         * get information from the estate and scan state
         */
-       scanstate = (FunctionScanState *) node->scan.scanstate;
-       estate = node->scan.plan.state;
+       estate = node->ss.ps.state;
        direction = estate->es_direction;
 
-       tuplestorestate = scanstate->tuplestorestate;
+       tuplestorestate = node->tuplestorestate;
 
        /*
         * If first time through, read all tuples from function and put them
@@ -74,13 +72,13 @@ FunctionNext(FunctionScan *node)
         */
        if (tuplestorestate == NULL)
        {
-               ExprContext *econtext = scanstate->csstate.cstate.cs_ExprContext;
+               ExprContext *econtext = node->ss.ps.ps_ExprContext;
                TupleDesc       funcTupdesc;
 
-               scanstate->tuplestorestate = tuplestorestate =
-                       ExecMakeTableFunctionResult(scanstate->funcexpr,
+               node->tuplestorestate = tuplestorestate =
+                       ExecMakeTableFunctionResult(node->funcexpr,
                                                                                econtext,
-                                                                               scanstate->tupdesc,
+                                                                               node->tupdesc,
                                                                                &funcTupdesc);
 
                /*
@@ -89,14 +87,14 @@ FunctionNext(FunctionScan *node)
                 * well do it always.
                 */
                if (funcTupdesc &&
-                       tupledesc_mismatch(scanstate->tupdesc, funcTupdesc))
+                       tupledesc_mismatch(node->tupdesc, funcTupdesc))
                        elog(ERROR, "Query-specified return tuple and actual function return tuple do not match");
        }
 
        /*
         * Get the next tuple from tuplestore. Return NULL if no more tuples.
         */
-       slot = scanstate->csstate.css_ScanTupleSlot;
+       slot = node->ss.ss_ScanTupleSlot;
        if (tuplestorestate)
                heapTuple = tuplestore_getheaptuple(tuplestorestate,
                                                                           ScanDirectionIsForward(direction),
@@ -121,20 +119,20 @@ FunctionNext(FunctionScan *node)
  */
 
 TupleTableSlot *
-ExecFunctionScan(FunctionScan *node)
+ExecFunctionScan(FunctionScanState *node)
 {
        /*
         * use FunctionNext as access method
         */
-       return ExecScan(&node->scan, (ExecScanAccessMtd) FunctionNext);
+       return ExecScan(&node->ss, (ExecScanAccessMtd) FunctionNext);
 }
 
 /* ----------------------------------------------------------------
  *             ExecInitFunctionScan
  * ----------------------------------------------------------------
  */
-bool
-ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
+FunctionScanState *
+ExecInitFunctionScan(FunctionScan *node, EState *estate)
 {
        FunctionScanState *scanstate;
        RangeTblEntry *rte;
@@ -145,34 +143,40 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
        /*
         * FunctionScan should not have any children.
         */
-       Assert(outerPlan((Plan *) node) == NULL);
-       Assert(innerPlan((Plan *) node) == NULL);
-
-       /*
-        * assign the node's execution state
-        */
-       node->scan.plan.state = estate;
+       Assert(outerPlan(node) == NULL);
+       Assert(innerPlan(node) == NULL);
 
        /*
         * create new ScanState for node
         */
        scanstate = makeNode(FunctionScanState);
-       node->scan.scanstate = &scanstate->csstate;
+       scanstate->ss.ps.plan = (Plan *) node;
+       scanstate->ss.ps.state = estate;
 
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &scanstate->csstate.cstate);
+       ExecAssignExprContext(estate, &scanstate->ss.ps);
 
 #define FUNCTIONSCAN_NSLOTS 2
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &scanstate->csstate.cstate);
-       ExecInitScanTupleSlot(estate, &scanstate->csstate);
+       ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
+       ExecInitScanTupleSlot(estate, &scanstate->ss);
+
+       /*
+        * initialize child expressions
+        */
+       scanstate->ss.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->scan.plan.targetlist,
+                                        (PlanState *) scanstate);
+       scanstate->ss.ps.qual = (List *)
+               ExecInitExpr((Node *) node->scan.plan.qual,
+                                        (PlanState *) scanstate);
 
        /*
         * get info about function
@@ -230,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
                elog(ERROR, "Unknown kind of return type specified for function");
 
        scanstate->tupdesc = tupdesc;
-       ExecSetSlotDescriptor(scanstate->csstate.css_ScanTupleSlot,
+       ExecSetSlotDescriptor(scanstate->ss.ss_ScanTupleSlot,
                                                  tupdesc, false);
 
        /*
@@ -239,15 +243,15 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
        scanstate->tuplestorestate = NULL;
        scanstate->funcexpr = rte->funcexpr;
 
-       scanstate->csstate.cstate.cs_TupFromTlist = false;
+       scanstate->ss.ps.ps_TupFromTlist = false;
 
        /*
         * initialize tuple type
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &scanstate->csstate.cstate);
-       ExecAssignProjectionInfo((Plan *) node, &scanstate->csstate.cstate);
+       ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+       ExecAssignProjectionInfo(&scanstate->ss.ps);
 
-       return TRUE;
+       return scanstate;
 }
 
 int
@@ -265,39 +269,26 @@ ExecCountSlotsFunctionScan(FunctionScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndFunctionScan(FunctionScan *node)
+ExecEndFunctionScan(FunctionScanState *node)
 {
-       FunctionScanState *scanstate;
-       EState     *estate;
-
-       /*
-        * get information from node
-        */
-       scanstate = (FunctionScanState *) node->scan.scanstate;
-       estate = node->scan.plan.state;
-
        /*
         * Free the projection info and the scan attribute info
-        *
-        * Note: we don't ExecFreeResultType(scanstate) because the rule manager
-        * depends on the tupType returned by ExecMain().  So for now, this is
-        * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&scanstate->csstate.cstate);
-       ExecFreeExprContext(&scanstate->csstate.cstate);
+       ExecFreeProjectionInfo(&node->ss.ps);
+       ExecFreeExprContext(&node->ss.ps);
 
        /*
         * clean out the tuple table
         */
-       ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot);
-       ExecClearTuple(scanstate->csstate.css_ScanTupleSlot);
+       ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+       ExecClearTuple(node->ss.ss_ScanTupleSlot);
 
        /*
         * Release tuplestore resources
         */
-       if (scanstate->tuplestorestate != NULL)
-               tuplestore_end(scanstate->tuplestorestate);
-       scanstate->tuplestorestate = NULL;
+       if (node->tuplestorestate != NULL)
+               tuplestore_end(node->tuplestorestate);
+       node->tuplestorestate = NULL;
 }
 
 /* ----------------------------------------------------------------
@@ -307,19 +298,15 @@ ExecEndFunctionScan(FunctionScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecFunctionMarkPos(FunctionScan *node)
+ExecFunctionMarkPos(FunctionScanState *node)
 {
-       FunctionScanState *scanstate;
-
-       scanstate = (FunctionScanState *) node->scan.scanstate;
-
        /*
         * if we haven't materialized yet, just return.
         */
-       if (!scanstate->tuplestorestate)
+       if (!node->tuplestorestate)
                return;
 
-       tuplestore_markpos(scanstate->tuplestorestate);
+       tuplestore_markpos(node->tuplestorestate);
 }
 
 /* ----------------------------------------------------------------
@@ -329,19 +316,15 @@ ExecFunctionMarkPos(FunctionScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecFunctionRestrPos(FunctionScan *node)
+ExecFunctionRestrPos(FunctionScanState *node)
 {
-       FunctionScanState *scanstate;
-
-       scanstate = (FunctionScanState *) node->scan.scanstate;
-
        /*
         * if we haven't materialized yet, just return.
         */
-       if (!scanstate->tuplestorestate)
+       if (!node->tuplestorestate)
                return;
 
-       tuplestore_restorepos(scanstate->tuplestorestate);
+       tuplestore_restorepos(node->tuplestorestate);
 }
 
 /* ----------------------------------------------------------------
@@ -351,21 +334,14 @@ ExecFunctionRestrPos(FunctionScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
 {
-       FunctionScanState *scanstate;
-
-       /*
-        * get information from node
-        */
-       scanstate = (FunctionScanState *) node->scan.scanstate;
-
-       ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot);
+       ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
        /*
         * If we haven't materialized yet, just return.
         */
-       if (!scanstate->tuplestorestate)
+       if (!node->tuplestorestate)
                return;
 
        /*
@@ -374,13 +350,13 @@ ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent)
         * whether the function expression contains parameters and/or is
         * marked volatile.  FIXME soon.
         */
-       if (node->scan.plan.chgParam != NULL)
+       if (node->ss.ps.chgParam != NULL)
        {
-               tuplestore_end(scanstate->tuplestorestate);
-               scanstate->tuplestorestate = NULL;
+               tuplestore_end(node->tuplestorestate);
+               node->tuplestorestate = NULL;
        }
        else
-               tuplestore_rescan(scanstate->tuplestorestate);
+               tuplestore_rescan(node->tuplestorestate);
 }
 
 
index d41bcbb..3d562a4 100644 (file)
@@ -15,7 +15,7 @@
  *       locate group boundaries.
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.50 2002/11/29 21:39:11 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.51 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  *             Return one tuple for each group of matching input tuples.
  */
 TupleTableSlot *
-ExecGroup(Group *node)
+ExecGroup(GroupState *node)
 {
-       GroupState *grpstate;
        EState     *estate;
        ExprContext *econtext;
        TupleDesc       tupdesc;
+       int                     numCols;
+       AttrNumber *grpColIdx;
        HeapTuple       outerTuple = NULL;
        HeapTuple       firsttuple;
        TupleTableSlot *outerslot;
@@ -53,12 +54,13 @@ ExecGroup(Group *node)
        /*
         * get state info from node
         */
-       grpstate = node->grpstate;
-       if (grpstate->grp_done)
+       if (node->grp_done)
                return NULL;
-       estate = node->plan.state;
-       econtext = node->grpstate->csstate.cstate.cs_ExprContext;
-       tupdesc = ExecGetScanType(&grpstate->csstate);
+       estate = node->ss.ps.state;
+       econtext = node->ss.ps.ps_ExprContext;
+       tupdesc = ExecGetScanType(&node->ss);
+       numCols = ((Group *) node->ss.ps.plan)->numCols;
+       grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
 
        /*
         * We need not call ResetExprContext here because execTuplesMatch will
@@ -67,16 +69,16 @@ ExecGroup(Group *node)
 
        /* If we don't already have first tuple of group, fetch it */
        /* this should occur on the first call only */
-       firsttuple = grpstate->grp_firstTuple;
+       firsttuple = node->grp_firstTuple;
        if (firsttuple == NULL)
        {
-               outerslot = ExecProcNode(outerPlan(node), (Plan *) node);
+               outerslot = ExecProcNode(outerPlanState(node));
                if (TupIsNull(outerslot))
                {
-                       grpstate->grp_done = TRUE;
+                       node->grp_done = TRUE;
                        return NULL;
                }
-               grpstate->grp_firstTuple = firsttuple =
+               node->grp_firstTuple = firsttuple =
                        heap_copytuple(outerslot->val);
        }
 
@@ -85,10 +87,10 @@ ExecGroup(Group *node)
         */
        for (;;)
        {
-               outerslot = ExecProcNode(outerPlan(node), (Plan *) node);
+               outerslot = ExecProcNode(outerPlanState(node));
                if (TupIsNull(outerslot))
                {
-                       grpstate->grp_done = TRUE;
+                       node->grp_done = TRUE;
                        outerTuple = NULL;
                        break;
                }
@@ -100,8 +102,8 @@ ExecGroup(Group *node)
                 */
                if (!execTuplesMatch(firsttuple, outerTuple,
                                                         tupdesc,
-                                                        node->numCols, node->grpColIdx,
-                                                        grpstate->eqfunctions,
+                                                        numCols, grpColIdx,
+                                                        node->eqfunctions,
                                                         econtext->ecxt_per_tuple_memory))
                        break;
        }
@@ -111,18 +113,18 @@ ExecGroup(Group *node)
         * group, and store it in the result tuple slot.
         */
        ExecStoreTuple(firsttuple,
-                                  grpstate->csstate.css_ScanTupleSlot,
+                                  node->ss.ss_ScanTupleSlot,
                                   InvalidBuffer,
                                   false);
-       econtext->ecxt_scantuple = grpstate->csstate.css_ScanTupleSlot;
-       projInfo = grpstate->csstate.cstate.cs_ProjInfo;
+       econtext->ecxt_scantuple = node->ss.ss_ScanTupleSlot;
+       projInfo = node->ss.ps.ps_ProjInfo;
        resultSlot = ExecProject(projInfo, NULL);
 
        /* save first tuple of next group, if we are not done yet */
-       if (!grpstate->grp_done)
+       if (!node->grp_done)
        {
                heap_freetuple(firsttuple);
-               grpstate->grp_firstTuple = heap_copytuple(outerTuple);
+               node->grp_firstTuple = heap_copytuple(outerTuple);
        }
 
        return resultSlot;
@@ -135,65 +137,69 @@ ExecGroup(Group *node)
  *     planner and initializes its outer subtree
  * -----------------
  */
-bool
-ExecInitGroup(Group *node, EState *estate, Plan *parent)
+GroupState *
+ExecInitGroup(Group *node, EState *estate)
 {
        GroupState *grpstate;
-       Plan       *outerPlan;
-
-       /*
-        * assign the node's execution state
-        */
-       node->plan.state = estate;
 
        /*
         * create state structure
         */
        grpstate = makeNode(GroupState);
-       node->grpstate = grpstate;
+       grpstate->ss.ps.plan = (Plan *) node;
+       grpstate->ss.ps.state = estate;
        grpstate->grp_firstTuple = NULL;
        grpstate->grp_done = FALSE;
 
        /*
         * create expression context
         */
-       ExecAssignExprContext(estate, &grpstate->csstate.cstate);
+       ExecAssignExprContext(estate, &grpstate->ss.ps);
 
 #define GROUP_NSLOTS 2
 
        /*
         * tuple table initialization
         */
-       ExecInitScanTupleSlot(estate, &grpstate->csstate);
-       ExecInitResultTupleSlot(estate, &grpstate->csstate.cstate);
+       ExecInitScanTupleSlot(estate, &grpstate->ss);
+       ExecInitResultTupleSlot(estate, &grpstate->ss.ps);
+
+       /*
+        * initialize child expressions
+        */
+       grpstate->ss.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->plan.targetlist,
+                                        (PlanState *) grpstate);
+       grpstate->ss.ps.qual = (List *)
+               ExecInitExpr((Node *) node->plan.qual,
+                                        (PlanState *) grpstate);
 
        /*
-        * initializes child nodes
+        * initialize child nodes
         */
-       outerPlan = outerPlan(node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
+       outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate);
 
        /*
         * initialize tuple type.
         */
-       ExecAssignScanTypeFromOuterPlan((Plan *) node, &grpstate->csstate);
+       ExecAssignScanTypeFromOuterPlan(&grpstate->ss);
 
        /*
         * Initialize tuple type for both result and scan. This node does no
         * projection
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &grpstate->csstate.cstate);
-       ExecAssignProjectionInfo((Plan *) node, &grpstate->csstate.cstate);
+       ExecAssignResultTypeFromTL(&grpstate->ss.ps);
+       ExecAssignProjectionInfo(&grpstate->ss.ps);
 
        /*
         * Precompute fmgr lookup data for inner loop
         */
        grpstate->eqfunctions =
-               execTuplesMatchPrepare(ExecGetScanType(&grpstate->csstate),
+               execTuplesMatchPrepare(ExecGetScanType(&grpstate->ss),
                                                           node->numCols,
                                                           node->grpColIdx);
 
-       return TRUE;
+       return grpstate;
 }
 
 int
@@ -208,43 +214,38 @@ ExecCountSlotsGroup(Group *node)
  * -----------------------
  */
 void
-ExecEndGroup(Group *node)
+ExecEndGroup(GroupState *node)
 {
-       GroupState *grpstate;
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
 
-       grpstate = node->grpstate;
+       ExecFreeProjectionInfo(&node->ss.ps);
+       ExecFreeExprContext(&node->ss.ps);
 
-       ExecFreeProjectionInfo(&grpstate->csstate.cstate);
-       ExecFreeExprContext(&grpstate->csstate.cstate);
-
-       outerPlan = outerPlan(node);
-       ExecEndNode(outerPlan, (Plan *) node);
+       outerPlan = outerPlanState(node);
+       ExecEndNode(outerPlan);
 
        /* clean up tuple table */
-       ExecClearTuple(grpstate->csstate.css_ScanTupleSlot);
-       if (grpstate->grp_firstTuple != NULL)
+       ExecClearTuple(node->ss.ss_ScanTupleSlot);
+       if (node->grp_firstTuple != NULL)
        {
-               heap_freetuple(grpstate->grp_firstTuple);
-               grpstate->grp_firstTuple = NULL;
+               heap_freetuple(node->grp_firstTuple);
+               node->grp_firstTuple = NULL;
        }
 }
 
 void
-ExecReScanGroup(Group *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanGroup(GroupState *node, ExprContext *exprCtxt)
 {
-       GroupState *grpstate = node->grpstate;
-
-       grpstate->grp_done = FALSE;
-       if (grpstate->grp_firstTuple != NULL)
+       node->grp_done = FALSE;
+       if (node->grp_firstTuple != NULL)
        {
-               heap_freetuple(grpstate->grp_firstTuple);
-               grpstate->grp_firstTuple = NULL;
+               heap_freetuple(node->grp_firstTuple);
+               node->grp_firstTuple = NULL;
        }
 
-       if (((Plan *) node)->lefttree &&
-               ((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree &&
+               ((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 }
 
 /*****************************************************************************
index c2c3ab6..9448ee4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.68 2002/11/30 00:08:15 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.69 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecHash(Hash *node)
+ExecHash(HashState *node)
 {
        EState     *estate;
-       HashState  *hashstate;
-       Plan       *outerNode;
+       PlanState  *outerNode;
        List       *hashkeys;
        HashJoinTable hashtable;
        TupleTableSlot *slot;
@@ -55,12 +54,10 @@ ExecHash(Hash *node)
        /*
         * get state info from node
         */
+       estate = node->ps.state;
+       outerNode = outerPlanState(node);
 
-       hashstate = node->hashstate;
-       estate = node->plan.state;
-       outerNode = outerPlan(node);
-
-       hashtable = hashstate->hashtable;
+       hashtable = node->hashtable;
        if (hashtable == NULL)
                elog(ERROR, "ExecHash: hash table is NULL.");
 
@@ -79,15 +76,15 @@ ExecHash(Hash *node)
        /*
         * set expression context
         */
-       hashkeys = node->hashkeys;
-       econtext = hashstate->cstate.cs_ExprContext;
+       hashkeys = ((Hash *) node->ps.plan)->hashkeys;
+       econtext = node->ps.ps_ExprContext;
 
        /*
         * get all inner tuples and insert into the hash table (or temp files)
         */
        for (;;)
        {
-               slot = ExecProcNode(outerNode, (Plan *) node);
+               slot = ExecProcNode(outerNode);
                if (TupIsNull(slot))
                        break;
                econtext->ecxt_innertuple = slot;
@@ -108,24 +105,19 @@ ExecHash(Hash *node)
  *             Init routine for Hash node
  * ----------------------------------------------------------------
  */
-bool
-ExecInitHash(Hash *node, EState *estate, Plan *parent)
+HashState *
+ExecInitHash(Hash *node, EState *estate)
 {
        HashState  *hashstate;
-       Plan       *outerPlan;
 
        SO_printf("ExecInitHash: initializing hash node\n");
 
        /*
-        * assign the node's execution state
-        */
-       node->plan.state = estate;
-
-       /*
         * create state structure
         */
        hashstate = makeNode(HashState);
-       node->hashstate = hashstate;
+       hashstate->ps.plan = (Plan *) node;
+       hashstate->ps.state = estate;
        hashstate->hashtable = NULL;
 
        /*
@@ -133,29 +125,38 @@ ExecInitHash(Hash *node, EState *estate, Plan *parent)
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &hashstate->cstate);
+       ExecAssignExprContext(estate, &hashstate->ps);
 
 #define HASH_NSLOTS 1
 
        /*
         * initialize our result slot
         */
-       ExecInitResultTupleSlot(estate, &hashstate->cstate);
+       ExecInitResultTupleSlot(estate, &hashstate->ps);
 
        /*
-        * initializes child nodes
+        * initialize child expressions
         */
-       outerPlan = outerPlan(node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
+       hashstate->ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->plan.targetlist,
+                                        (PlanState *) hashstate);
+       hashstate->ps.qual = (List *)
+               ExecInitExpr((Node *) node->plan.qual,
+                                        (PlanState *) hashstate);
+
+       /*
+        * initialize child nodes
+        */
+       outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate);
 
        /*
         * initialize tuple type. no need to initialize projection info
         * because this node doesn't do projections
         */
-       ExecAssignResultTypeFromOuterPlan((Plan *) node, &hashstate->cstate);
-       hashstate->cstate.cs_ProjInfo = NULL;
+       ExecAssignResultTypeFromOuterPlan(&hashstate->ps);
+       hashstate->ps.ps_ProjInfo = NULL;
 
-       return TRUE;
+       return hashstate;
 }
 
 int
@@ -173,28 +174,22 @@ ExecCountSlotsHash(Hash *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndHash(Hash *node)
+ExecEndHash(HashState *node)
 {
-       HashState  *hashstate;
-       Plan       *outerPlan;
-
-       /*
-        * get info from the hash state
-        */
-       hashstate = node->hashstate;
+       PlanState  *outerPlan;
 
        /*
         * free projection info.  no need to free result type info because
         * that came from the outer plan...
         */
-       ExecFreeProjectionInfo(&hashstate->cstate);
-       ExecFreeExprContext(&hashstate->cstate);
+       ExecFreeProjectionInfo(&node->ps);
+       ExecFreeExprContext(&node->ps);
 
        /*
         * shut down the subplan
         */
-       outerPlan = outerPlan(node);
-       ExecEndNode(outerPlan, (Plan *) node);
+       outerPlan = outerPlanState(node);
+       ExecEndNode(outerPlan);
 }
 
 
@@ -758,12 +753,12 @@ ExecHashTableReset(HashJoinTable hashtable, long ntuples)
 }
 
 void
-ExecReScanHash(Hash *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanHash(HashState *node, ExprContext *exprCtxt)
 {
        /*
         * if chgParam of subnode is not null then plan will be re-scanned by
         * first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 }
index 8f0e700..06796c5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.42 2002/11/30 00:08:15 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.43 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,8 +22,8 @@
 #include "utils/memutils.h"
 
 
-static TupleTableSlot *ExecHashJoinOuterGetTuple(Plan *node, Plan *parent,
-                                                 HashJoinState *hjstate);
+static TupleTableSlot *ExecHashJoinOuterGetTuple(PlanState *node,
+                                                                                                HashJoinState *hjstate);
 static TupleTableSlot *ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
                                                  BufFile *file,
                                                  TupleTableSlot *tupleSlot);
@@ -41,12 +41,11 @@ static int  ExecHashJoinNewBatch(HashJoinState *hjstate);
  * ----------------------------------------------------------------
  */
 TupleTableSlot *                               /* return: a tuple or NULL */
-ExecHashJoin(HashJoin *node)
+ExecHashJoin(HashJoinState *node)
 {
-       HashJoinState *hjstate;
        EState     *estate;
-       Plan       *outerNode;
-       Hash       *hashNode;
+       PlanState  *outerNode;
+       HashState  *hashNode;
        List       *hjclauses;
        List       *outerkeys;
        List       *joinqual;
@@ -65,37 +64,36 @@ ExecHashJoin(HashJoin *node)
        /*
         * get information from HashJoin node
         */
-       hjstate = node->hashjoinstate;
        hjclauses = node->hashclauses;
-       estate = node->join.plan.state;
-       joinqual = node->join.joinqual;
-       otherqual = node->join.plan.qual;
-       hashNode = (Hash *) innerPlan(node);
-       outerNode = outerPlan(node);
-       hashPhaseDone = hjstate->hj_hashdone;
+       estate = node->js.ps.state;
+       joinqual = node->js.joinqual;
+       otherqual = node->js.ps.qual;
+       hashNode = (HashState *) innerPlanState(node);
+       outerNode = outerPlanState(node);
+       hashPhaseDone = node->hj_hashdone;
        dir = estate->es_direction;
 
        /*
         * get information from HashJoin state
         */
-       hashtable = hjstate->hj_HashTable;
-       outerkeys = hjstate->hj_OuterHashKeys;
-       econtext = hjstate->jstate.cs_ExprContext;
+       hashtable = node->hj_HashTable;
+       outerkeys = node->hj_OuterHashKeys;
+       econtext = node->js.ps.ps_ExprContext;
 
        /*
         * Check to see if we're still projecting out tuples from a previous
         * join tuple (because there is a function-returning-set in the
         * projection expressions).  If so, try to project another one.
         */
-       if (hjstate->jstate.cs_TupFromTlist)
+       if (node->js.ps.ps_TupFromTlist)
        {
                TupleTableSlot *result;
 
-               result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone);
+               result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
                if (isDone == ExprMultipleResult)
                        return result;
                /* Done with that source tuple... */
-               hjstate->jstate.cs_TupFromTlist = false;
+               node->js.ps.ps_TupFromTlist = false;
        }
 
        /*
@@ -116,16 +114,16 @@ ExecHashJoin(HashJoin *node)
                        /*
                         * create the hash table
                         */
-                       hashtable = ExecHashTableCreate(hashNode);
-                       hjstate->hj_HashTable = hashtable;
+                       hashtable = ExecHashTableCreate((Hash *) hashNode->ps.plan);
+                       node->hj_HashTable = hashtable;
 
                        /*
                         * execute the Hash node, to build the hash table
                         */
-                       hashNode->hashstate->hashtable = hashtable;
-                       innerTupleSlot = ExecProcNode((Plan *) hashNode, (Plan *) node);
+                       hashNode->hashtable = hashtable;
+                       innerTupleSlot = ExecProcNode((PlanState *) hashNode);
                }
-               hjstate->hj_hashdone = true;
+               node->hj_hashdone = true;
 
                /*
                 * Open temp files for outer batches, if needed. Note that file
@@ -140,40 +138,39 @@ ExecHashJoin(HashJoin *node)
        /*
         * Now get an outer tuple and probe into the hash table for matches
         */
-       outerTupleSlot = hjstate->jstate.cs_OuterTupleSlot;
+       outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
 
        for (;;)
        {
                /*
                 * If we don't have an outer tuple, get the next one
                 */
-               if (hjstate->hj_NeedNewOuter)
+               if (node->hj_NeedNewOuter)
                {
                        outerTupleSlot = ExecHashJoinOuterGetTuple(outerNode,
-                                                                                                          (Plan *) node,
-                                                                                                          hjstate);
+                                                                                                          node);
                        if (TupIsNull(outerTupleSlot))
                        {
                                /*
                                 * when the last batch runs out, clean up and exit
                                 */
                                ExecHashTableDestroy(hashtable);
-                               hjstate->hj_HashTable = NULL;
+                               node->hj_HashTable = NULL;
                                return NULL;
                        }
 
-                       hjstate->jstate.cs_OuterTupleSlot = outerTupleSlot;
+                       node->js.ps.ps_OuterTupleSlot = outerTupleSlot;
                        econtext->ecxt_outertuple = outerTupleSlot;
-                       hjstate->hj_NeedNewOuter = false;
-                       hjstate->hj_MatchedOuter = false;
+                       node->hj_NeedNewOuter = false;
+                       node->hj_MatchedOuter = false;
 
                        /*
                         * now we have an outer tuple, find the corresponding bucket
                         * for this tuple from the hash table
                         */
-                       hjstate->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext,
+                       node->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext,
                                                                                                                outerkeys);
-                       hjstate->hj_CurTuple = NULL;
+                       node->hj_CurTuple = NULL;
 
                        /*
                         * Now we've got an outer tuple and the corresponding hash
@@ -182,7 +179,7 @@ ExecHashJoin(HashJoin *node)
                         */
                        if (hashtable->curbatch == 0)
                        {
-                               int                     batch = ExecHashJoinGetBatch(hjstate->hj_CurBucketNo,
+                               int                     batch = ExecHashJoinGetBatch(node->hj_CurBucketNo,
                                                                                                                 hashtable);
 
                                if (batch > 0)
@@ -196,7 +193,7 @@ ExecHashJoin(HashJoin *node)
                                        hashtable->outerBatchSize[batchno]++;
                                        ExecHashJoinSaveTuple(outerTupleSlot->val,
                                                                         hashtable->outerBatchFile[batchno]);
-                                       hjstate->hj_NeedNewOuter = true;
+                                       node->hj_NeedNewOuter = true;
                                        continue;       /* loop around for a new outer tuple */
                                }
                        }
@@ -207,7 +204,7 @@ ExecHashJoin(HashJoin *node)
                 */
                for (;;)
                {
-                       curtuple = ExecScanHashBucket(hjstate,
+                       curtuple = ExecScanHashBucket(node,
                                                                                  hjclauses,
                                                                                  econtext);
                        if (curtuple == NULL)
@@ -217,7 +214,7 @@ ExecHashJoin(HashJoin *node)
                         * we've got a match, but still need to test non-hashed quals
                         */
                        inntuple = ExecStoreTuple(curtuple,
-                                                                         hjstate->hj_HashTupleSlot,
+                                                                         node->hj_HashTupleSlot,
                                                                          InvalidBuffer,
                                                                          false);       /* don't pfree this tuple */
                        econtext->ecxt_innertuple = inntuple;
@@ -235,17 +232,17 @@ ExecHashJoin(HashJoin *node)
                         */
                        if (ExecQual(joinqual, econtext, false))
                        {
-                               hjstate->hj_MatchedOuter = true;
+                               node->hj_MatchedOuter = true;
 
                                if (otherqual == NIL || ExecQual(otherqual, econtext, false))
                                {
                                        TupleTableSlot *result;
 
-                                       result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone);
+                                       result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
 
                                        if (isDone != ExprEndResult)
                                        {
-                                               hjstate->jstate.cs_TupFromTlist =
+                                               node->js.ps.ps_TupFromTlist =
                                                        (isDone == ExprMultipleResult);
                                                return result;
                                        }
@@ -258,10 +255,10 @@ ExecHashJoin(HashJoin *node)
                 * whether to emit a dummy outer-join tuple. If not, loop around
                 * to get a new outer tuple.
                 */
-               hjstate->hj_NeedNewOuter = true;
+               node->hj_NeedNewOuter = true;
 
-               if (!hjstate->hj_MatchedOuter &&
-                       node->join.jointype == JOIN_LEFT)
+               if (!node->hj_MatchedOuter &&
+                       node->js.jointype == JOIN_LEFT)
                {
                        /*
                         * We are doing an outer join and there were no join matches
@@ -269,7 +266,7 @@ ExecHashJoin(HashJoin *node)
                         * nulls for the inner tuple, and return it if it passes the
                         * non-join quals.
                         */
-                       econtext->ecxt_innertuple = hjstate->hj_NullInnerTupleSlot;
+                       econtext->ecxt_innertuple = node->hj_NullInnerTupleSlot;
 
                        if (ExecQual(otherqual, econtext, false))
                        {
@@ -280,11 +277,11 @@ ExecHashJoin(HashJoin *node)
                                 */
                                TupleTableSlot *result;
 
-                               result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone);
+                               result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
 
                                if (isDone != ExprEndResult)
                                {
-                                       hjstate->jstate.cs_TupFromTlist =
+                                       node->js.ps.ps_TupFromTlist =
                                                (isDone == ExprMultipleResult);
                                        return result;
                                }
@@ -299,8 +296,8 @@ ExecHashJoin(HashJoin *node)
  *             Init routine for HashJoin node.
  * ----------------------------------------------------------------
  */
-bool                                                   /* return: initialization status */
-ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
+HashJoinState *
+ExecInitHashJoin(HashJoin *node, EState *estate)
 {
        HashJoinState *hjstate;
        Plan       *outerNode;
@@ -308,38 +305,51 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
        List       *hcl;
 
        /*
-        * assign the node's execution state
-        */
-       node->join.plan.state = estate;
-
-       /*
         * create state structure
         */
        hjstate = makeNode(HashJoinState);
-       node->hashjoinstate = hjstate;
+       hjstate->js.ps.plan = (Plan *) node;
+       hjstate->js.ps.state = estate;
 
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &hjstate->jstate);
+       ExecAssignExprContext(estate, &hjstate->js.ps);
+
+       /*
+        * initialize child expressions
+        */
+       hjstate->js.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->join.plan.targetlist,
+                                        (PlanState *) hjstate);
+       hjstate->js.ps.qual = (List *)
+               ExecInitExpr((Node *) node->join.plan.qual,
+                                        (PlanState *) hjstate);
+       hjstate->js.jointype = node->join.jointype;
+       hjstate->js.joinqual = (List *)
+               ExecInitExpr((Node *) node->join.joinqual,
+                                        (PlanState *) hjstate);
+       hjstate->hashclauses = (List *)
+               ExecInitExpr((Node *) node->hashclauses,
+                                        (PlanState *) hjstate);
 
        /*
-        * initializes child nodes
+        * initialize child nodes
         */
-       outerNode = outerPlan((Plan *) node);
-       hashNode = (Hash *) innerPlan((Plan *) node);
+       outerNode = outerPlan(node);
+       hashNode = (Hash *) innerPlan(node);
 
-       ExecInitNode(outerNode, estate, (Plan *) node);
-       ExecInitNode((Plan *) hashNode, estate, (Plan *) node);
+       outerPlanState(hjstate) = ExecInitNode(outerNode, estate);
+       innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate);
 
 #define HASHJOIN_NSLOTS 3
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &hjstate->jstate);
+       ExecInitResultTupleSlot(estate, &hjstate->js.ps);
        hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
 
        switch (node->join.jointype)
@@ -349,7 +359,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
                case JOIN_LEFT:
                        hjstate->hj_NullInnerTupleSlot =
                                ExecInitNullTupleSlot(estate,
-                                                                         ExecGetTupType((Plan *) hashNode));
+                                                                         ExecGetTupType(innerPlanState(hjstate)));
                        break;
                default:
                        elog(ERROR, "ExecInitHashJoin: unsupported join type %d",
@@ -364,8 +374,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
         * the contents of the hash table.      -cim 6/9/91
         */
        {
-               HashState  *hashstate = hashNode->hashstate;
-               TupleTableSlot *slot = hashstate->cstate.cs_ResultTupleSlot;
+               HashState  *hashstate = (HashState *) innerPlanState(hjstate);
+               TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot;
 
                hjstate->hj_HashTupleSlot = slot;
        }
@@ -373,11 +383,11 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
        /*
         * initialize tuple type and projection info
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &hjstate->jstate);
-       ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate);
+       ExecAssignResultTypeFromTL(&hjstate->js.ps);
+       ExecAssignProjectionInfo(&hjstate->js.ps);
 
        ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot,
-                                                 ExecGetTupType(outerNode),
+                                                 ExecGetTupType(outerPlanState(hjstate)),
                                                  false);
 
        /*
@@ -402,12 +412,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
                                                                                        get_leftop(lfirst(hcl)));
        }
 
-       hjstate->jstate.cs_OuterTupleSlot = NULL;
-       hjstate->jstate.cs_TupFromTlist = false;
+       hjstate->js.ps.ps_OuterTupleSlot = NULL;
+       hjstate->js.ps.ps_TupFromTlist = false;
        hjstate->hj_NeedNewOuter = true;
        hjstate->hj_MatchedOuter = false;
 
-       return TRUE;
+       return hjstate;
 }
 
 int
@@ -425,46 +435,35 @@ ExecCountSlotsHashJoin(HashJoin *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndHashJoin(HashJoin *node)
+ExecEndHashJoin(HashJoinState *node)
 {
-       HashJoinState *hjstate;
-
-       /*
-        * get info from the HashJoin state
-        */
-       hjstate = node->hashjoinstate;
-
        /*
         * free hash table in case we end plan before all tuples are retrieved
         */
-       if (hjstate->hj_HashTable)
+       if (node->hj_HashTable)
        {
-               ExecHashTableDestroy(hjstate->hj_HashTable);
-               hjstate->hj_HashTable = NULL;
+               ExecHashTableDestroy(node->hj_HashTable);
+               node->hj_HashTable = NULL;
        }
 
        /*
         * Free the projection info and the scan attribute info
-        *
-        * Note: we don't ExecFreeResultType(hjstate) because the rule manager
-        * depends on the tupType returned by ExecMain().  So for now, this is
-        * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&hjstate->jstate);
-       ExecFreeExprContext(&hjstate->jstate);
+       ExecFreeProjectionInfo(&node->js.ps);
+       ExecFreeExprContext(&node->js.ps);
 
        /*
         * clean up subtrees
         */
-       ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
-       ExecEndNode(innerPlan((Plan *) node), (Plan *) node);
+       ExecEndNode(outerPlanState(node));
+       ExecEndNode(innerPlanState(node));
 
        /*
         * clean out the tuple table
         */
-       ExecClearTuple(hjstate->jstate.cs_ResultTupleSlot);
-       ExecClearTuple(hjstate->hj_OuterTupleSlot);
-       ExecClearTuple(hjstate->hj_HashTupleSlot);
+       ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
+       ExecClearTuple(node->hj_OuterTupleSlot);
+       ExecClearTuple(node->hj_HashTupleSlot);
 
 }
 
@@ -478,7 +477,7 @@ ExecEndHashJoin(HashJoin *node)
  */
 
 static TupleTableSlot *
-ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate)
+ExecHashJoinOuterGetTuple(PlanState *node, HashJoinState *hjstate)
 {
        HashJoinTable hashtable = hjstate->hj_HashTable;
        int                     curbatch = hashtable->curbatch;
@@ -486,7 +485,7 @@ ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate)
 
        if (curbatch == 0)
        {                                                       /* if it is the first pass */
-               slot = ExecProcNode(node, parent);
+               slot = ExecProcNode(node);
                if (!TupIsNull(slot))
                        return slot;
 
@@ -611,7 +610,7 @@ ExecHashJoinNewBatch(HashJoinState *hjstate)
         */
        ExecHashTableReset(hashtable, innerBatchSize[newbatch - 1]);
 
-       econtext = hjstate->jstate.cs_ExprContext;
+       econtext = hjstate->js.ps.ps_ExprContext;
        innerhashkeys = hjstate->hj_InnerHashKeys;
 
        while ((slot = ExecHashJoinGetSavedTuple(hjstate,
@@ -682,39 +681,37 @@ ExecHashJoinSaveTuple(HeapTuple heapTuple,
 }
 
 void
-ExecReScanHashJoin(HashJoin *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
 {
-       HashJoinState *hjstate = node->hashjoinstate;
-
-       if (!hjstate->hj_hashdone)
+       if (!node->hj_hashdone)
                return;
 
-       hjstate->hj_hashdone = false;
+       node->hj_hashdone = false;
 
        /*
         * Unfortunately, currently we have to destroy hashtable in all
         * cases...
         */
-       if (hjstate->hj_HashTable)
+       if (node->hj_HashTable)
        {
-               ExecHashTableDestroy(hjstate->hj_HashTable);
-               hjstate->hj_HashTable = NULL;
+               ExecHashTableDestroy(node->hj_HashTable);
+               node->hj_HashTable = NULL;
        }
 
-       hjstate->hj_CurBucketNo = 0;
-       hjstate->hj_CurTuple = (HashJoinTuple) NULL;
+       node->hj_CurBucketNo = 0;
+       node->hj_CurTuple = (HashJoinTuple) NULL;
 
-       hjstate->jstate.cs_OuterTupleSlot = (TupleTableSlot *) NULL;
-       hjstate->jstate.cs_TupFromTlist = false;
-       hjstate->hj_NeedNewOuter = true;
-       hjstate->hj_MatchedOuter = false;
+       node->js.ps.ps_OuterTupleSlot = (TupleTableSlot *) NULL;
+       node->js.ps.ps_TupFromTlist = false;
+       node->hj_NeedNewOuter = true;
+       node->hj_MatchedOuter = false;
 
        /*
         * if chgParam of subnodes is not null then plans will be re-scanned
         * by first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
-       if (((Plan *) node)->righttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+       if (((PlanState *) node)->righttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->righttree, exprCtxt);
 }
index 78f5ad0..e9888c4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.71 2002/09/04 20:31:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.72 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,7 +40,7 @@
 #define LEFT_OP                        1
 #define RIGHT_OP               2
 
-static TupleTableSlot *IndexNext(IndexScan *node);
+static TupleTableSlot *IndexNext(IndexScanState *node);
 
 /* ----------------------------------------------------------------
  *             IndexNext
@@ -65,15 +65,14 @@ static TupleTableSlot *IndexNext(IndexScan *node);
  * ----------------------------------------------------------------
  */
 static TupleTableSlot *
-IndexNext(IndexScan *node)
+IndexNext(IndexScanState *node)
 {
        EState     *estate;
-       CommonScanState *scanstate;
-       IndexScanState *indexstate;
        ExprContext *econtext;
        ScanDirection direction;
        IndexScanDescPtr scanDescs;
        IndexScanDesc scandesc;
+       Index           scanrelid;
        HeapTuple       tuple;
        TupleTableSlot *slot;
        int                     numIndices;
@@ -83,21 +82,20 @@ IndexNext(IndexScan *node)
        /*
         * extract necessary information from index scan node
         */
-       estate = node->scan.plan.state;
+       estate = node->ss.ps.state;
        direction = estate->es_direction;
-       if (ScanDirectionIsBackward(node->indxorderdir))
+       if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir))
        {
                if (ScanDirectionIsForward(direction))
                        direction = BackwardScanDirection;
                else if (ScanDirectionIsBackward(direction))
                        direction = ForwardScanDirection;
        }
-       scanstate = node->scan.scanstate;
-       indexstate = node->indxstate;
-       scanDescs = indexstate->iss_ScanDescs;
-       numIndices = indexstate->iss_NumIndices;
-       econtext = scanstate->cstate.cs_ExprContext;
-       slot = scanstate->css_ScanTupleSlot;
+       scanDescs = node->iss_ScanDescs;
+       numIndices = node->iss_NumIndices;
+       econtext = node->ss.ps.ps_ExprContext;
+       slot = node->ss.ss_ScanTupleSlot;
+       scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;
 
        /*
         * Check if we are evaluating PlanQual for tuple of this relation.
@@ -106,15 +104,15 @@ IndexNext(IndexScan *node)
         * switching in Init/ReScan plan...
         */
        if (estate->es_evTuple != NULL &&
-               estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+               estate->es_evTuple[scanrelid - 1] != NULL)
        {
                List       *qual;
 
                ExecClearTuple(slot);
-               if (estate->es_evTupleNull[node->scan.scanrelid - 1])
+               if (estate->es_evTupleNull[scanrelid - 1])
                        return slot;            /* return empty slot */
 
-               ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
+               ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
                                           slot, InvalidBuffer, false);
 
                /* Does the tuple meet any of the OR'd indxqual conditions? */
@@ -131,7 +129,7 @@ IndexNext(IndexScan *node)
                        slot->val = NULL;
 
                /* Flag for the next call that no more tuples */
-               estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
+               estate->es_evTupleNull[scanrelid - 1] = true;
 
                return slot;
        }
@@ -144,24 +142,24 @@ IndexNext(IndexScan *node)
        bBackward = ScanDirectionIsBackward(direction);
        if (bBackward)
        {
-               indexNumber = numIndices - indexstate->iss_IndexPtr - 1;
+               indexNumber = numIndices - node->iss_IndexPtr - 1;
                if (indexNumber < 0)
                {
                        indexNumber = 0;
-                       indexstate->iss_IndexPtr = numIndices - 1;
+                       node->iss_IndexPtr = numIndices - 1;
                }
        }
        else
        {
-               if ((indexNumber = indexstate->iss_IndexPtr) < 0)
+               if ((indexNumber = node->iss_IndexPtr) < 0)
                {
                        indexNumber = 0;
-                       indexstate->iss_IndexPtr = 0;
+                       node->iss_IndexPtr = 0;
                }
        }
        while (indexNumber < numIndices)
        {
-               scandesc = scanDescs[indexstate->iss_IndexPtr];
+               scandesc = scanDescs[node->iss_IndexPtr];
                while ((tuple = index_getnext(scandesc, direction)) != NULL)
                {
                        /*
@@ -181,7 +179,7 @@ IndexNext(IndexScan *node)
                         * We do this by passing the tuple through ExecQual and
                         * checking for failure with all previous qualifications.
                         */
-                       if (indexstate->iss_IndexPtr > 0)
+                       if (node->iss_IndexPtr > 0)
                        {
                                bool            prev_matches = false;
                                int                     prev_index;
@@ -191,7 +189,7 @@ IndexNext(IndexScan *node)
                                ResetExprContext(econtext);
                                qual = node->indxqualorig;
                                for (prev_index = 0;
-                                        prev_index < indexstate->iss_IndexPtr;
+                                        prev_index < node->iss_IndexPtr;
                                         prev_index++)
                                {
                                        if (ExecQual((List *) lfirst(qual), econtext, false))
@@ -216,9 +214,9 @@ IndexNext(IndexScan *node)
                {
                        indexNumber++;
                        if (bBackward)
-                               indexstate->iss_IndexPtr--;
+                               node->iss_IndexPtr--;
                        else
-                               indexstate->iss_IndexPtr++;
+                               node->iss_IndexPtr++;
                }
        }
 
@@ -251,21 +249,19 @@ IndexNext(IndexScan *node)
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecIndexScan(IndexScan *node)
+ExecIndexScan(IndexScanState *node)
 {
-       IndexScanState *indexstate = node->indxstate;
-
        /*
         * If we have runtime keys and they've not already been set up, do it
         * now.
         */
-       if (indexstate->iss_RuntimeKeyInfo && !indexstate->iss_RuntimeKeysReady)
-               ExecReScan((Plan *) node, NULL, NULL);
+       if (node->iss_RuntimeKeyInfo && !node->iss_RuntimeKeysReady)
+               ExecReScan((PlanState *) node, NULL);
 
        /*
         * use IndexNext as access method
         */
-       return ExecScan(&node->scan, (ExecScanAccessMtd) IndexNext);
+       return ExecScan(&node->ss, (ExecScanAccessMtd) IndexNext);
 }
 
 /* ----------------------------------------------------------------
@@ -280,28 +276,27 @@ ExecIndexScan(IndexScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
 {
        EState     *estate;
-       IndexScanState *indexstate;
        ExprContext *econtext;
        int                     numIndices;
        IndexScanDescPtr scanDescs;
        ScanKey    *scanKeys;
        int               **runtimeKeyInfo;
        int                *numScanKeys;
+       Index           scanrelid;
        int                     i;
        int                     j;
 
-       estate = node->scan.plan.state;
-       indexstate = node->indxstate;
-       econtext = indexstate->iss_RuntimeContext;      /* context for runtime
-                                                                                                * keys */
-       numIndices = indexstate->iss_NumIndices;
-       scanDescs = indexstate->iss_ScanDescs;
-       scanKeys = indexstate->iss_ScanKeys;
-       runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
-       numScanKeys = indexstate->iss_NumScanKeys;
+       estate = node->ss.ps.state;
+       econtext = node->iss_RuntimeContext;    /* context for runtime keys */
+       numIndices = node->iss_NumIndices;
+       scanDescs = node->iss_ScanDescs;
+       scanKeys = node->iss_ScanKeys;
+       runtimeKeyInfo = node->iss_RuntimeKeyInfo;
+       numScanKeys = node->iss_NumScanKeys;
+       scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;
 
        if (econtext)
        {
@@ -315,7 +310,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
                        ExprContext *stdecontext;
 
                        econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
-                       stdecontext = node->scan.scanstate->cstate.cs_ExprContext;
+                       stdecontext = node->ss.ps.ps_ExprContext;
                        stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
                }
 
@@ -392,22 +387,22 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
                        }
                }
 
-               indexstate->iss_RuntimeKeysReady = true;
+               node->iss_RuntimeKeysReady = true;
        }
 
        /* If this is re-scanning of PlanQual ... */
        if (estate->es_evTuple != NULL &&
-               estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+               estate->es_evTuple[scanrelid - 1] != NULL)
        {
-               estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
+               estate->es_evTupleNull[scanrelid - 1] = false;
                return;
        }
 
        /* reset index scans */
-       if (ScanDirectionIsBackward(node->indxorderdir))
-               indexstate->iss_IndexPtr = numIndices;
+       if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir))
+               node->iss_IndexPtr = numIndices;
        else
-               indexstate->iss_IndexPtr = -1;
+               node->iss_IndexPtr = -1;
 
        for (i = 0; i < numIndices; i++)
        {
@@ -427,13 +422,10 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
  * ----------------------------------------------------------------
  */
 void
-ExecEndIndexScan(IndexScan *node)
+ExecEndIndexScan(IndexScanState *node)
 {
-       CommonScanState *scanstate;
-       IndexScanState *indexstate;
        int               **runtimeKeyInfo;
        ScanKey    *scanKeys;
-       List       *indxqual;
        int                *numScanKeys;
        int                     numIndices;
        Relation        relation;
@@ -441,32 +433,25 @@ ExecEndIndexScan(IndexScan *node)
        IndexScanDescPtr indexScanDescs;
        int                     i;
 
-       scanstate = node->scan.scanstate;
-       indexstate = node->indxstate;
-       indxqual = node->indxqual;
-       runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
+       runtimeKeyInfo = node->iss_RuntimeKeyInfo;
 
        /*
         * extract information from the node
         */
-       numIndices = indexstate->iss_NumIndices;
-       scanKeys = indexstate->iss_ScanKeys;
-       numScanKeys = indexstate->iss_NumScanKeys;
-       indexRelationDescs = indexstate->iss_RelationDescs;
-       indexScanDescs = indexstate->iss_ScanDescs;
-       relation = scanstate->css_currentRelation;
+       numIndices = node->iss_NumIndices;
+       scanKeys = node->iss_ScanKeys;
+       numScanKeys = node->iss_NumScanKeys;
+       indexRelationDescs = node->iss_RelationDescs;
+       indexScanDescs = node->iss_ScanDescs;
+       relation = node->ss.ss_currentRelation;
 
        /*
         * Free the projection info and the scan attribute info
-        *
-        * Note: we don't ExecFreeResultType(scanstate) because the rule manager
-        * depends on the tupType returned by ExecMain().  So for now, this is
-        * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&scanstate->cstate);
-       ExecFreeExprContext(&scanstate->cstate);
-       if (indexstate->iss_RuntimeContext)
-               FreeExprContext(indexstate->iss_RuntimeContext);
+       ExecFreeProjectionInfo(&node->ss.ps);
+       ExecFreeExprContext(&node->ss.ps);
+       if (node->iss_RuntimeContext)
+               FreeExprContext(node->iss_RuntimeContext);
 
        /*
         * close the index relations
@@ -514,12 +499,11 @@ ExecEndIndexScan(IndexScan *node)
        /*
         * clear out tuple table slots
         */
-       ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
-       ExecClearTuple(scanstate->css_ScanTupleSlot);
-       pfree(scanstate);
-       pfree(indexstate->iss_RelationDescs);
-       pfree(indexstate->iss_ScanDescs);
-       pfree(indexstate);
+       ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+       ExecClearTuple(node->ss.ss_ScanTupleSlot);
+       pfree(node->iss_RelationDescs);
+       pfree(node->iss_ScanDescs);
+       pfree(node);
 }
 
 /* ----------------------------------------------------------------
@@ -531,21 +515,16 @@ ExecEndIndexScan(IndexScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecIndexMarkPos(IndexScan *node)
+ExecIndexMarkPos(IndexScanState *node)
 {
-       IndexScanState *indexstate;
        IndexScanDescPtr indexScanDescs;
        IndexScanDesc scanDesc;
        int                     indexPtr;
 
-       indexstate = node->indxstate;
-       indexPtr = indexstate->iss_MarkIndexPtr = indexstate->iss_IndexPtr;
-       indexScanDescs = indexstate->iss_ScanDescs;
+       indexPtr = node->iss_MarkIndexPtr = node->iss_IndexPtr;
+       indexScanDescs = node->iss_ScanDescs;
        scanDesc = indexScanDescs[indexPtr];
 
-#ifdef NOT_USED
-       IndexScanMarkPosition(scanDesc);
-#endif
        index_markpos(scanDesc);
 }
 
@@ -560,21 +539,16 @@ ExecIndexMarkPos(IndexScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecIndexRestrPos(IndexScan *node)
+ExecIndexRestrPos(IndexScanState *node)
 {
-       IndexScanState *indexstate;
        IndexScanDescPtr indexScanDescs;
        IndexScanDesc scanDesc;
        int                     indexPtr;
 
-       indexstate = node->indxstate;
-       indexPtr = indexstate->iss_IndexPtr = indexstate->iss_MarkIndexPtr;
-       indexScanDescs = indexstate->iss_ScanDescs;
+       indexPtr = node->iss_IndexPtr = node->iss_MarkIndexPtr;
+       indexScanDescs = node->iss_ScanDescs;
        scanDesc = indexScanDescs[indexPtr];
 
-#ifdef NOT_USED
-       IndexScanRestorePosition(scanDesc);
-#endif
        index_restrpos(scanDesc);
 }
 
@@ -597,11 +571,10 @@ ExecIndexRestrPos(IndexScan *node)
  *               estate: the execution state initialized in InitPlan.
  * ----------------------------------------------------------------
  */
-bool
-ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
+IndexScanState *
+ExecInitIndexScan(IndexScan *node, EState *estate)
 {
        IndexScanState *indexstate;
-       CommonScanState *scanstate;
        List       *indxqual;
        List       *indxid;
        List       *listscan;
@@ -620,45 +593,52 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
        Relation        currentRelation;
 
        /*
-        * assign execution state to node
+        * create state structure
         */
-       node->scan.plan.state = estate;
+       indexstate = makeNode(IndexScanState);
+       indexstate->ss.ps.plan = (Plan *) node;
+       indexstate->ss.ps.state = estate;
 
        /*
-        * Part 1)      initialize scan state
+        * Miscellaneous initialization
         *
-        * create new CommonScanState for node
+        * create expression context for node
         */
-       scanstate = makeNode(CommonScanState);
-       node->scan.scanstate = scanstate;
+       ExecAssignExprContext(estate, &indexstate->ss.ps);
 
        /*
-        * Miscellaneous initialization
-        *
-        * create expression context for node
+        * initialize child expressions
         */
-       ExecAssignExprContext(estate, &scanstate->cstate);
+       indexstate->ss.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->scan.plan.targetlist,
+                                        (PlanState *) indexstate);
+       indexstate->ss.ps.qual = (List *)
+               ExecInitExpr((Node *) node->scan.plan.qual,
+                                        (PlanState *) indexstate);
+       indexstate->indxqual = (List *)
+               ExecInitExpr((Node *) node->indxqual,
+                                        (PlanState *) indexstate);
+       indexstate->indxqualorig = (List *)
+               ExecInitExpr((Node *) node->indxqualorig,
+                                        (PlanState *) indexstate);
 
 #define INDEXSCAN_NSLOTS 2
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &scanstate->cstate);
-       ExecInitScanTupleSlot(estate, scanstate);
+       ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
+       ExecInitScanTupleSlot(estate, &indexstate->ss);
 
        /*
         * initialize projection info.  result type comes from scan desc
         * below..
         */
-       ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
+       ExecAssignProjectionInfo(&indexstate->ss.ps);
 
        /*
-        * Part 2)      initialize index scan state
-        *
-        * create new IndexScanState for node
+        * Initialize index-specific scan state
         */
-       indexstate = makeNode(IndexScanState);
        indexstate->iss_NumIndices = 0;
        indexstate->iss_IndexPtr = -1;
        indexstate->iss_ScanKeys = NULL;
@@ -669,8 +649,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
        indexstate->iss_RelationDescs = NULL;
        indexstate->iss_ScanDescs = NULL;
 
-       node->indxstate = indexstate;
-
        /*
         * get the index node information
         */
@@ -836,7 +814,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
                                {
                                        /* treat Param like a constant */
                                        scanvalue = ExecEvalParam((Param *) leftop,
-                                                                               scanstate->cstate.cs_ExprContext,
+                                                                               indexstate->ss.ps.ps_ExprContext,
                                                                                          &isnull);
                                        if (isnull)
                                                flags |= SK_ISNULL;
@@ -911,7 +889,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
                                {
                                        /* treat Param like a constant */
                                        scanvalue = ExecEvalParam((Param *) rightop,
-                                                                               scanstate->cstate.cs_ExprContext,
+                                                                               indexstate->ss.ps.ps_ExprContext,
                                                                                          &isnull);
                                        if (isnull)
                                                flags |= SK_ISNULL;
@@ -976,12 +954,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
         */
        if (have_runtime_keys)
        {
-               ExprContext *stdecontext = scanstate->cstate.cs_ExprContext;
+               ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
 
-               ExecAssignExprContext(estate, &scanstate->cstate);
+               ExecAssignExprContext(estate, &indexstate->ss.ps);
                indexstate->iss_RuntimeKeyInfo = runtimeKeyInfo;
-               indexstate->iss_RuntimeContext = scanstate->cstate.cs_ExprContext;
-               scanstate->cstate.cs_ExprContext = stdecontext;
+               indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
+               indexstate->ss.ps.ps_ExprContext = stdecontext;
        }
        else
        {
@@ -1008,14 +986,14 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
        if (!RelationGetForm(currentRelation)->relhasindex)
                elog(ERROR, "indexes of the relation %u was inactivated", reloid);
 
-       scanstate->css_currentRelation = currentRelation;
-       scanstate->css_currentScanDesc = NULL;          /* no heap scan here */
+       indexstate->ss.ss_currentRelation = currentRelation;
+       indexstate->ss.ss_currentScanDesc = NULL;               /* no heap scan here */
 
        /*
         * get the scan type from the relation descriptor.
         */
-       ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
-       ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
+       ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation), false);
+       ExecAssignResultTypeFromTL(&indexstate->ss.ps);
 
        /*
         * open the index relations and initialize relation and scan
@@ -1043,7 +1021,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
        /*
         * all done.
         */
-       return TRUE;
+       return indexstate;
 }
 
 int
index 4b22b93..1ea3aa6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.11 2002/11/22 22:10:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.12 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,7 @@
 #include "executor/executor.h"
 #include "executor/nodeLimit.h"
 
-static void recompute_limits(Limit *node);
+static void recompute_limits(LimitState *node);
 
 
 /* ----------------------------------------------------------------
@@ -35,26 +35,24 @@ static void recompute_limits(Limit *node);
  * ----------------------------------------------------------------
  */
 TupleTableSlot *                               /* return: a tuple or NULL */
-ExecLimit(Limit *node)
+ExecLimit(LimitState *node)
 {
-       LimitState *limitstate;
        ScanDirection direction;
        TupleTableSlot *resultTupleSlot;
        TupleTableSlot *slot;
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
 
        /*
         * get information from the node
         */
-       limitstate = node->limitstate;
-       direction = node->plan.state->es_direction;
-       outerPlan = outerPlan((Plan *) node);
-       resultTupleSlot = limitstate->cstate.cs_ResultTupleSlot;
+       direction = node->ps.state->es_direction;
+       outerPlan = outerPlanState(node);
+       resultTupleSlot = node->ps.ps_ResultTupleSlot;
 
        /*
         * The main logic is a simple state machine.
         */
-       switch (limitstate->lstate)
+       switch (node->lstate)
        {
                case LIMIT_INITIAL:
                        /*
@@ -71,9 +69,9 @@ ExecLimit(Limit *node)
                        /*
                         * Check for empty window; if so, treat like empty subplan.
                         */
-                       if (limitstate->count <= 0 && !limitstate->noCount)
+                       if (node->count <= 0 && !node->noCount)
                        {
-                               limitstate->lstate = LIMIT_EMPTY;
+                               node->lstate = LIMIT_EMPTY;
                                return NULL;
                        }
                        /*
@@ -81,24 +79,24 @@ ExecLimit(Limit *node)
                         */
                        for (;;)
                        {
-                               slot = ExecProcNode(outerPlan, (Plan *) node);
+                               slot = ExecProcNode(outerPlan);
                                if (TupIsNull(slot))
                                {
                                        /*
                                         * The subplan returns too few tuples for us to produce
                                         * any output at all.
                                         */
-                                       limitstate->lstate = LIMIT_EMPTY;
+                                       node->lstate = LIMIT_EMPTY;
                                        return NULL;
                                }
-                               limitstate->subSlot = slot;
-                               if (++limitstate->position > limitstate->offset)
+                               node->subSlot = slot;
+                               if (++node->position > node->offset)
                                        break;
                        }
                        /*
                         * Okay, we have the first tuple of the window.
                         */
-                       limitstate->lstate = LIMIT_INWINDOW;
+                       node->lstate = LIMIT_INWINDOW;
                        break;
 
                case LIMIT_EMPTY:
@@ -117,23 +115,23 @@ ExecLimit(Limit *node)
                                 * advancing the subplan or the position variable; but
                                 * change the state machine state to record having done so.
                                 */
-                               if (!limitstate->noCount &&
-                                       limitstate->position >= limitstate->offset + limitstate->count)
+                               if (!node->noCount &&
+                                       node->position >= node->offset + node->count)
                                {
-                                       limitstate->lstate = LIMIT_WINDOWEND;
+                                       node->lstate = LIMIT_WINDOWEND;
                                        return NULL;
                                }
                                /*
                                 * Get next tuple from subplan, if any.
                                 */
-                               slot = ExecProcNode(outerPlan, (Plan *) node);
+                               slot = ExecProcNode(outerPlan);
                                if (TupIsNull(slot))
                                {
-                                       limitstate->lstate = LIMIT_SUBPLANEOF;
+                                       node->lstate = LIMIT_SUBPLANEOF;
                                        return NULL;
                                }
-                               limitstate->subSlot = slot;
-                               limitstate->position++;
+                               node->subSlot = slot;
+                               node->position++;
                        }
                        else
                        {
@@ -141,19 +139,19 @@ ExecLimit(Limit *node)
                                 * Backwards scan, so check for stepping off start of window.
                                 * As above, change only state-machine status if so.
                                 */
-                               if (limitstate->position <= limitstate->offset + 1)
+                               if (node->position <= node->offset + 1)
                                {
-                                       limitstate->lstate = LIMIT_WINDOWSTART;
+                                       node->lstate = LIMIT_WINDOWSTART;
                                        return NULL;
                                }
                                /*
                                 * Get previous tuple from subplan; there should be one!
                                 */
-                               slot = ExecProcNode(outerPlan, (Plan *) node);
+                               slot = ExecProcNode(outerPlan);
                                if (TupIsNull(slot))
                                        elog(ERROR, "ExecLimit: subplan failed to run backwards");
-                               limitstate->subSlot = slot;
-                               limitstate->position--;
+                               node->subSlot = slot;
+                               node->position--;
                        }
                        break;
 
@@ -164,11 +162,11 @@ ExecLimit(Limit *node)
                         * Backing up from subplan EOF, so re-fetch previous tuple;
                         * there should be one!  Note previous tuple must be in window.
                         */
-                       slot = ExecProcNode(outerPlan, (Plan *) node);
+                       slot = ExecProcNode(outerPlan);
                        if (TupIsNull(slot))
                                elog(ERROR, "ExecLimit: subplan failed to run backwards");
-                       limitstate->subSlot = slot;
-                       limitstate->lstate = LIMIT_INWINDOW;
+                       node->subSlot = slot;
+                       node->lstate = LIMIT_INWINDOW;
                        /* position does not change 'cause we didn't advance it before */
                        break;
 
@@ -179,8 +177,8 @@ ExecLimit(Limit *node)
                         * Backing up from window end: simply re-return the last
                         * tuple fetched from the subplan.
                         */
-                       slot = limitstate->subSlot;
-                       limitstate->lstate = LIMIT_INWINDOW;
+                       slot = node->subSlot;
+                       node->lstate = LIMIT_INWINDOW;
                        /* position does not change 'cause we didn't advance it before */
                        break;
 
@@ -191,14 +189,14 @@ ExecLimit(Limit *node)
                         * Advancing after having backed off window start: simply
                         * re-return the last tuple fetched from the subplan.
                         */
-                       slot = limitstate->subSlot;
-                       limitstate->lstate = LIMIT_INWINDOW;
+                       slot = node->subSlot;
+                       node->lstate = LIMIT_INWINDOW;
                        /* position does not change 'cause we didn't change it before */
                        break;
 
                default:
                        elog(ERROR, "ExecLimit: impossible state %d",
-                                (int) limitstate->lstate);
+                                (int) node->lstate);
                        slot = NULL;            /* keep compiler quiet */
                        break;
        }
@@ -220,55 +218,54 @@ ExecLimit(Limit *node)
  * This is also a handy place to reset the current-position state info.
  */
 static void
-recompute_limits(Limit *node)
+recompute_limits(LimitState *node)
 {
-       LimitState *limitstate = node->limitstate;
-       ExprContext *econtext = limitstate->cstate.cs_ExprContext;
+       ExprContext *econtext = node->ps.ps_ExprContext;
        bool            isNull;
 
        if (node->limitOffset)
        {
-               limitstate->offset =
+               node->offset =
                        DatumGetInt32(ExecEvalExprSwitchContext(node->limitOffset,
                                                                                                        econtext,
                                                                                                        &isNull,
                                                                                                        NULL));
                /* Interpret NULL offset as no offset */
                if (isNull)
-                       limitstate->offset = 0;
-               else if (limitstate->offset < 0)
-                       limitstate->offset = 0;
+                       node->offset = 0;
+               else if (node->offset < 0)
+                       node->offset = 0;
        }
        else
        {
                /* No OFFSET supplied */
-               limitstate->offset = 0;
+               node->offset = 0;
        }
 
        if (node->limitCount)
        {
-               limitstate->noCount = false;
-               limitstate->count =
+               node->noCount = false;
+               node->count =
                        DatumGetInt32(ExecEvalExprSwitchContext(node->limitCount,
                                                                                                        econtext,
                                                                                                        &isNull,
                                                                                                        NULL));
                /* Interpret NULL count as no count (LIMIT ALL) */
                if (isNull)
-                       limitstate->noCount = true;
-               else if (limitstate->count < 0)
-                       limitstate->count = 0;
+                       node->noCount = true;
+               else if (node->count < 0)
+                       node->count = 0;
        }
        else
        {
                /* No COUNT supplied */
-               limitstate->count = 0;
-               limitstate->noCount = true;
+               node->count = 0;
+               node->noCount = true;
        }
 
        /* Reset position to start-of-scan */
-       limitstate->position = 0;
-       limitstate->subSlot = NULL;
+       node->position = 0;
+       node->subSlot = NULL;
 }
 
 /* ----------------------------------------------------------------
@@ -278,22 +275,19 @@ recompute_limits(Limit *node)
  *             the node's subplan.
  * ----------------------------------------------------------------
  */
-bool                                                   /* return: initialization status */
-ExecInitLimit(Limit *node, EState *estate, Plan *parent)
+LimitState *
+ExecInitLimit(Limit *node, EState *estate)
 {
        LimitState *limitstate;
        Plan       *outerPlan;
 
        /*
-        * assign execution state to node
-        */
-       node->plan.state = estate;
-
-       /*
-        * create new LimitState for node
+        * create state structure
         */
        limitstate = makeNode(LimitState);
-       node->limitstate = limitstate;
+       limitstate->ps.plan = (Plan *) node;
+       limitstate->ps.state = estate;
+
        limitstate->lstate = LIMIT_INITIAL;
 
        /*
@@ -302,29 +296,37 @@ ExecInitLimit(Limit *node, EState *estate, Plan *parent)
         * Limit nodes never call ExecQual or ExecProject, but they need an
         * exprcontext anyway to evaluate the limit/offset parameters in.
         */
-       ExecAssignExprContext(estate, &limitstate->cstate);
+       ExecAssignExprContext(estate, &limitstate->ps);
+
+       /*
+        * initialize child expressions
+        */
+       limitstate->limitOffset = ExecInitExpr(node->limitOffset,
+                                                                                  (PlanState *) limitstate);
+       limitstate->limitCount = ExecInitExpr(node->limitCount,
+                                                                                 (PlanState *) limitstate);
 
 #define LIMIT_NSLOTS 1
 
        /*
         * Tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &limitstate->cstate);
+       ExecInitResultTupleSlot(estate, &limitstate->ps);
 
        /*
         * then initialize outer plan
         */
-       outerPlan = outerPlan((Plan *) node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
+       outerPlan = outerPlan(node);
+       outerPlanState(limitstate) = ExecInitNode(outerPlan, estate);
 
        /*
         * limit nodes do no projections, so initialize projection info for
         * this node appropriately
         */
-       ExecAssignResultTypeFromOuterPlan((Plan *) node, &limitstate->cstate);
-       limitstate->cstate.cs_ProjInfo = NULL;
+       ExecAssignResultTypeFromOuterPlan(&limitstate->ps);
+       limitstate->ps.ps_ProjInfo = NULL;
 
-       return TRUE;
+       return limitstate;
 }
 
 int
@@ -343,33 +345,29 @@ ExecCountSlotsLimit(Limit *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndLimit(Limit *node)
+ExecEndLimit(LimitState *node)
 {
-       LimitState *limitstate = node->limitstate;
+       ExecFreeExprContext(&node->ps);
 
-       ExecFreeExprContext(&limitstate->cstate);
-
-       ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
+       ExecEndNode(outerPlanState(node));
 
        /* clean up tuple table */
-       ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot);
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
 }
 
 
 void
-ExecReScanLimit(Limit *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanLimit(LimitState *node, ExprContext *exprCtxt)
 {
-       LimitState *limitstate = node->limitstate;
-
        /* resetting lstate will force offset/limit recalculation */
-       limitstate->lstate = LIMIT_INITIAL;
+       node->lstate = LIMIT_INITIAL;
 
-       ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot);
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
 
        /*
         * if chgParam of subnode is not null then plan will be re-scanned by
         * first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 }
index 30eb9a2..cf7ca89 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.38 2002/06/20 20:29:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.39 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * ----------------------------------------------------------------
  */
 TupleTableSlot *                               /* result tuple from subplan */
-ExecMaterial(Material *node)
+ExecMaterial(MaterialState *node)
 {
        EState     *estate;
-       MaterialState *matstate;
        ScanDirection dir;
        Tuplestorestate *tuplestorestate;
        HeapTuple       heapTuple;
@@ -56,10 +55,9 @@ ExecMaterial(Material *node)
        /*
         * get state info from node
         */
-       matstate = node->matstate;
-       estate = node->plan.state;
+       estate = node->ss.ps.state;
        dir = estate->es_direction;
-       tuplestorestate = (Tuplestorestate *) matstate->tuplestorestate;
+       tuplestorestate = (Tuplestorestate *) node->tuplestorestate;
 
        /*
         * If first time through, read all tuples from outer plan and pass
@@ -69,7 +67,7 @@ ExecMaterial(Material *node)
 
        if (tuplestorestate == NULL)
        {
-               Plan       *outerNode;
+               PlanState  *outerNode;
 
                /*
                 * Want to scan subplan in the forward direction while creating
@@ -84,16 +82,16 @@ ExecMaterial(Material *node)
                tuplestorestate = tuplestore_begin_heap(true,   /* randomAccess */
                                                                                                SortMem);
 
-               matstate->tuplestorestate = (void *) tuplestorestate;
+               node->tuplestorestate = (void *) tuplestorestate;
 
                /*
                 * Scan the subplan and feed all the tuples to tuplestore.
                 */
-               outerNode = outerPlan((Plan *) node);
+               outerNode = outerPlanState(node);
 
                for (;;)
                {
-                       slot = ExecProcNode(outerNode, (Plan *) node);
+                       slot = ExecProcNode(outerNode);
 
                        if (TupIsNull(slot))
                                break;
@@ -117,7 +115,7 @@ ExecMaterial(Material *node)
         * Get the first or next tuple from tuplestore. Returns NULL if no
         * more tuples.
         */
-       slot = (TupleTableSlot *) matstate->csstate.cstate.cs_ResultTupleSlot;
+       slot = (TupleTableSlot *) node->ss.ps.ps_ResultTupleSlot;
        heapTuple = tuplestore_getheaptuple(tuplestorestate,
                                                                                ScanDirectionIsForward(dir),
                                                                                &should_free);
@@ -129,23 +127,20 @@ ExecMaterial(Material *node)
  *             ExecInitMaterial
  * ----------------------------------------------------------------
  */
-bool                                                   /* initialization status */
-ExecInitMaterial(Material *node, EState *estate, Plan *parent)
+MaterialState *
+ExecInitMaterial(Material *node, EState *estate)
 {
        MaterialState *matstate;
        Plan       *outerPlan;
 
        /*
-        * assign the node's execution state
-        */
-       node->plan.state = estate;
-
-       /*
         * create state structure
         */
        matstate = makeNode(MaterialState);
+       matstate->ss.ps.plan = (Plan *) node;
+       matstate->ss.ps.state = estate;
+
        matstate->tuplestorestate = NULL;
-       node->matstate = matstate;
 
        /*
         * Miscellaneous initialization
@@ -161,24 +156,24 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
         *
         * material nodes only return tuples from their materialized relation.
         */
-       ExecInitResultTupleSlot(estate, &matstate->csstate.cstate);
-       ExecInitScanTupleSlot(estate, &matstate->csstate);
+       ExecInitResultTupleSlot(estate, &matstate->ss.ps);
+       ExecInitScanTupleSlot(estate, &matstate->ss);
 
        /*
         * initializes child nodes
         */
-       outerPlan = outerPlan((Plan *) node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
+       outerPlan = outerPlan(node);
+       outerPlanState(matstate) = ExecInitNode(outerPlan, estate);
 
        /*
         * initialize tuple type.  no need to initialize projection info
         * because this node doesn't do projections.
         */
-       ExecAssignResultTypeFromOuterPlan((Plan *) node, &matstate->csstate.cstate);
-       ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate);
-       matstate->csstate.cstate.cs_ProjInfo = NULL;
+       ExecAssignResultTypeFromOuterPlan(&matstate->ss.ps);
+       ExecAssignScanTypeFromOuterPlan(&matstate->ss);
+       matstate->ss.ps.ps_ProjInfo = NULL;
 
-       return TRUE;
+       return matstate;
 }
 
 int
@@ -194,33 +189,24 @@ ExecCountSlotsMaterial(Material *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndMaterial(Material *node)
+ExecEndMaterial(MaterialState *node)
 {
-       MaterialState *matstate;
-       Plan       *outerPlan;
-
        /*
-        * get info from the material state
+        * clean out the tuple table
         */
-       matstate = node->matstate;
+       ExecClearTuple(node->ss.ss_ScanTupleSlot);
 
        /*
         * shut down the subplan
         */
-       outerPlan = outerPlan((Plan *) node);
-       ExecEndNode(outerPlan, (Plan *) node);
-
-       /*
-        * clean out the tuple table
-        */
-       ExecClearTuple(matstate->csstate.css_ScanTupleSlot);
+       ExecEndNode(outerPlanState(node));
 
        /*
         * Release tuplestore resources
         */
-       if (matstate->tuplestorestate != NULL)
-               tuplestore_end((Tuplestorestate *) matstate->tuplestorestate);
-       matstate->tuplestorestate = NULL;
+       if (node->tuplestorestate != NULL)
+               tuplestore_end((Tuplestorestate *) node->tuplestorestate);
+       node->tuplestorestate = NULL;
 }
 
 /* ----------------------------------------------------------------
@@ -230,17 +216,15 @@ ExecEndMaterial(Material *node)
  * ----------------------------------------------------------------
  */
 void
-ExecMaterialMarkPos(Material *node)
+ExecMaterialMarkPos(MaterialState *node)
 {
-       MaterialState *matstate = node->matstate;
-
        /*
         * if we haven't materialized yet, just return.
         */
-       if (!matstate->tuplestorestate)
+       if (!node->tuplestorestate)
                return;
 
-       tuplestore_markpos((Tuplestorestate *) matstate->tuplestorestate);
+       tuplestore_markpos((Tuplestorestate *) node->tuplestorestate);
 }
 
 /* ----------------------------------------------------------------
@@ -250,20 +234,18 @@ ExecMaterialMarkPos(Material *node)
  * ----------------------------------------------------------------
  */
 void
-ExecMaterialRestrPos(Material *node)
+ExecMaterialRestrPos(MaterialState *node)
 {
-       MaterialState *matstate = node->matstate;
-
        /*
         * if we haven't materialized yet, just return.
         */
-       if (!matstate->tuplestorestate)
+       if (!node->tuplestorestate)
                return;
 
        /*
         * restore the scan to the previously marked position
         */
-       tuplestore_restorepos((Tuplestorestate *) matstate->tuplestorestate);
+       tuplestore_restorepos((Tuplestorestate *) node->tuplestorestate);
 }
 
 /* ----------------------------------------------------------------
@@ -273,19 +255,17 @@ ExecMaterialRestrPos(Material *node)
  * ----------------------------------------------------------------
  */
 void
-ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
+ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
 {
-       MaterialState *matstate = node->matstate;
-
        /*
         * If we haven't materialized yet, just return. If outerplan' chgParam
         * is not NULL then it will be re-scanned by ExecProcNode, else - no
         * reason to re-scan it at all.
         */
-       if (!matstate->tuplestorestate)
+       if (!node->tuplestorestate)
                return;
 
-       ExecClearTuple(matstate->csstate.cstate.cs_ResultTupleSlot);
+       ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
        /*
         * If subnode is to be rescanned then we forget previous stored
@@ -293,11 +273,11 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
         *
         * Otherwise we can just rewind and rescan the stored output.
         */
-       if (((Plan *) node)->lefttree->chgParam != NULL)
+       if (((PlanState *) node)->lefttree->chgParam != NULL)
        {
-               tuplestore_end((Tuplestorestate *) matstate->tuplestorestate);
-               matstate->tuplestorestate = NULL;
+               tuplestore_end((Tuplestorestate *) node->tuplestorestate);
+               node->tuplestorestate = NULL;
        }
        else
-               tuplestore_rescan((Tuplestorestate *) matstate->tuplestorestate);
+               tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
 }
index 4237618..171738d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.51 2002/09/04 20:31:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.52 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -340,10 +340,9 @@ ExecMergeTupleDump(MergeJoinState *mergestate)
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecMergeJoin(MergeJoin *node)
+ExecMergeJoin(MergeJoinState *node)
 {
        EState     *estate;
-       MergeJoinState *mergestate;
        ScanDirection direction;
        List       *innerSkipQual;
        List       *outerSkipQual;
@@ -352,9 +351,9 @@ ExecMergeJoin(MergeJoin *node)
        List       *otherqual;
        bool            qualResult;
        bool            compareResult;
-       Plan       *innerPlan;
+       PlanState   *innerPlan;
        TupleTableSlot *innerTupleSlot;
-       Plan       *outerPlan;
+       PlanState   *outerPlan;
        TupleTableSlot *outerTupleSlot;
        ExprContext *econtext;
        bool            doFillOuter;
@@ -363,17 +362,16 @@ ExecMergeJoin(MergeJoin *node)
        /*
         * get information from node
         */
-       mergestate = node->mergestate;
-       estate = node->join.plan.state;
+       estate = node->js.ps.state;
        direction = estate->es_direction;
-       innerPlan = innerPlan((Plan *) node);
-       outerPlan = outerPlan((Plan *) node);
-       econtext = mergestate->jstate.cs_ExprContext;
+       innerPlan = innerPlanState(node);
+       outerPlan = outerPlanState(node);
+       econtext = node->js.ps.ps_ExprContext;
        mergeclauses = node->mergeclauses;
-       joinqual = node->join.joinqual;
-       otherqual = node->join.plan.qual;
+       joinqual = node->js.joinqual;
+       otherqual = node->js.ps.qual;
 
-       switch (node->join.jointype)
+       switch (node->js.jointype)
        {
                case JOIN_INNER:
                        doFillOuter = false;
@@ -393,7 +391,7 @@ ExecMergeJoin(MergeJoin *node)
                        break;
                default:
                        elog(ERROR, "ExecMergeJoin: unsupported join type %d",
-                                (int) node->join.jointype);
+                                (int) node->js.jointype);
                        doFillOuter = false;    /* keep compiler quiet */
                        doFillInner = false;
                        break;
@@ -401,13 +399,13 @@ ExecMergeJoin(MergeJoin *node)
 
        if (ScanDirectionIsForward(direction))
        {
-               outerSkipQual = mergestate->mj_OuterSkipQual;
-               innerSkipQual = mergestate->mj_InnerSkipQual;
+               outerSkipQual = node->mj_OuterSkipQual;
+               innerSkipQual = node->mj_InnerSkipQual;
        }
        else
        {
-               outerSkipQual = mergestate->mj_InnerSkipQual;
-               innerSkipQual = mergestate->mj_OuterSkipQual;
+               outerSkipQual = node->mj_InnerSkipQual;
+               innerSkipQual = node->mj_OuterSkipQual;
        }
 
        /*
@@ -415,16 +413,16 @@ ExecMergeJoin(MergeJoin *node)
         * join tuple (because there is a function-returning-set in the
         * projection expressions).  If so, try to project another one.
         */
-       if (mergestate->jstate.cs_TupFromTlist)
+       if (node->js.ps.ps_TupFromTlist)
        {
                TupleTableSlot *result;
                ExprDoneCond isDone;
 
-               result = ExecProject(mergestate->jstate.cs_ProjInfo, &isDone);
+               result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
                if (isDone == ExprMultipleResult)
                        return result;
                /* Done with that source tuple... */
-               mergestate->jstate.cs_TupFromTlist = false;
+               node->js.ps.ps_TupFromTlist = false;
        }
 
        /*
@@ -444,9 +442,9 @@ ExecMergeJoin(MergeJoin *node)
                 * Note: The join states are highlighted with 32-* comments for
                 * improved readability.
                 */
-               MJ_dump(mergestate);
+               MJ_dump(node);
 
-               switch (mergestate->mj_JoinState)
+               switch (node->mj_JoinState)
                {
                                /*
                                 * EXEC_MJ_INITIALIZE means that this is the first time
@@ -459,8 +457,8 @@ ExecMergeJoin(MergeJoin *node)
                        case EXEC_MJ_INITIALIZE:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
 
-                               outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
-                               mergestate->mj_OuterTupleSlot = outerTupleSlot;
+                               outerTupleSlot = ExecProcNode(outerPlan);
+                               node->mj_OuterTupleSlot = outerTupleSlot;
                                if (TupIsNull(outerTupleSlot))
                                {
                                        MJ_printf("ExecMergeJoin: outer subplan is empty\n");
@@ -471,16 +469,16 @@ ExecMergeJoin(MergeJoin *node)
                                                 * inner tuples.  We set MatchedInner = true to
                                                 * force the ENDOUTER state to advance inner.
                                                 */
-                                               mergestate->mj_JoinState = EXEC_MJ_ENDOUTER;
-                                               mergestate->mj_MatchedInner = true;
+                                               node->mj_JoinState = EXEC_MJ_ENDOUTER;
+                                               node->mj_MatchedInner = true;
                                                break;
                                        }
                                        /* Otherwise we're done. */
                                        return NULL;
                                }
 
-                               innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
-                               mergestate->mj_InnerTupleSlot = innerTupleSlot;
+                               innerTupleSlot = ExecProcNode(innerPlan);
+                               node->mj_InnerTupleSlot = innerTupleSlot;
                                if (TupIsNull(innerTupleSlot))
                                {
                                        MJ_printf("ExecMergeJoin: inner subplan is empty\n");
@@ -493,8 +491,8 @@ ExecMergeJoin(MergeJoin *node)
                                                 * state to emit this tuple before advancing
                                                 * outer.
                                                 */
-                                               mergestate->mj_JoinState = EXEC_MJ_ENDINNER;
-                                               mergestate->mj_MatchedOuter = false;
+                                               node->mj_JoinState = EXEC_MJ_ENDINNER;
+                                               node->mj_MatchedOuter = false;
                                                break;
                                        }
                                        /* Otherwise we're done. */
@@ -505,7 +503,7 @@ ExecMergeJoin(MergeJoin *node)
                                 * OK, we have the initial tuples.      Begin by skipping
                                 * unmatched inner tuples.
                                 */
-                               mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
+                               node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
                                break;
 
                                /*
@@ -519,9 +517,9 @@ ExecMergeJoin(MergeJoin *node)
 
                                ExecMarkPos(innerPlan);
 
-                               MarkInnerTuple(mergestate->mj_InnerTupleSlot, mergestate);
+                               MarkInnerTuple(node->mj_InnerTupleSlot, node);
 
-                               mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+                               node->mj_JoinState = EXEC_MJ_JOINTEST;
                                break;
 
                                /*
@@ -538,18 +536,18 @@ ExecMergeJoin(MergeJoin *node)
 
                                ResetExprContext(econtext);
 
-                               outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                               outerTupleSlot = node->mj_OuterTupleSlot;
                                econtext->ecxt_outertuple = outerTupleSlot;
-                               innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                               innerTupleSlot = node->mj_InnerTupleSlot;
                                econtext->ecxt_innertuple = innerTupleSlot;
 
                                qualResult = ExecQual(mergeclauses, econtext, false);
                                MJ_DEBUG_QUAL(mergeclauses, qualResult);
 
                                if (qualResult)
-                                       mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+                                       node->mj_JoinState = EXEC_MJ_JOINTUPLES;
                                else
-                                       mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
+                                       node->mj_JoinState = EXEC_MJ_NEXTOUTER;
                                break;
 
                                /*
@@ -560,7 +558,7 @@ ExecMergeJoin(MergeJoin *node)
                        case EXEC_MJ_JOINTUPLES:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");
 
-                               mergestate->mj_JoinState = EXEC_MJ_NEXTINNER;
+                               node->mj_JoinState = EXEC_MJ_NEXTINNER;
 
                                /*
                                 * Check the extra qual conditions to see if we actually
@@ -582,8 +580,8 @@ ExecMergeJoin(MergeJoin *node)
 
                                if (qualResult)
                                {
-                                       mergestate->mj_MatchedOuter = true;
-                                       mergestate->mj_MatchedInner = true;
+                                       node->mj_MatchedOuter = true;
+                                       node->mj_MatchedInner = true;
 
                                        qualResult = (otherqual == NIL ||
                                                                  ExecQual(otherqual, econtext, false));
@@ -601,12 +599,12 @@ ExecMergeJoin(MergeJoin *node)
 
                                                MJ_printf("ExecMergeJoin: returning tuple\n");
 
-                                               result = ExecProject(mergestate->jstate.cs_ProjInfo,
+                                               result = ExecProject(node->js.ps.ps_ProjInfo,
                                                                                         &isDone);
 
                                                if (isDone != ExprEndResult)
                                                {
-                                                       mergestate->jstate.cs_TupFromTlist =
+                                                       node->js.ps.ps_TupFromTlist =
                                                                (isDone == ExprMultipleResult);
                                                        return result;
                                                }
@@ -625,20 +623,20 @@ ExecMergeJoin(MergeJoin *node)
                        case EXEC_MJ_NEXTINNER:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");
 
-                               if (doFillInner && !mergestate->mj_MatchedInner)
+                               if (doFillInner && !node->mj_MatchedInner)
                                {
                                        /*
                                         * Generate a fake join tuple with nulls for the outer
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       mergestate->mj_MatchedInner = true; /* do it only once */
+                                       node->mj_MatchedInner = true; /* do it only once */
 
                                        ResetExprContext(econtext);
 
-                                       outerTupleSlot = mergestate->mj_NullOuterTupleSlot;
+                                       outerTupleSlot = node->mj_NullOuterTupleSlot;
                                        econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                                       innerTupleSlot = node->mj_InnerTupleSlot;
                                        econtext->ecxt_innertuple = innerTupleSlot;
 
                                        if (ExecQual(otherqual, econtext, false))
@@ -653,12 +651,12 @@ ExecMergeJoin(MergeJoin *node)
 
                                                MJ_printf("ExecMergeJoin: returning fill tuple\n");
 
-                                               result = ExecProject(mergestate->jstate.cs_ProjInfo,
+                                               result = ExecProject(node->js.ps.ps_ProjInfo,
                                                                                         &isDone);
 
                                                if (isDone != ExprEndResult)
                                                {
-                                                       mergestate->jstate.cs_TupFromTlist =
+                                                       node->js.ps.ps_TupFromTlist =
                                                                (isDone == ExprMultipleResult);
                                                        return result;
                                                }
@@ -668,15 +666,15 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * now we get the next inner tuple, if any
                                 */
-                               innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
-                               mergestate->mj_InnerTupleSlot = innerTupleSlot;
+                               innerTupleSlot = ExecProcNode(innerPlan);
+                               node->mj_InnerTupleSlot = innerTupleSlot;
                                MJ_DEBUG_PROC_NODE(innerTupleSlot);
-                               mergestate->mj_MatchedInner = false;
+                               node->mj_MatchedInner = false;
 
                                if (TupIsNull(innerTupleSlot))
-                                       mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
+                                       node->mj_JoinState = EXEC_MJ_NEXTOUTER;
                                else
-                                       mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+                                       node->mj_JoinState = EXEC_MJ_JOINTEST;
                                break;
 
                                /*-------------------------------------------
@@ -701,20 +699,20 @@ ExecMergeJoin(MergeJoin *node)
                        case EXEC_MJ_NEXTOUTER:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");
 
-                               if (doFillOuter && !mergestate->mj_MatchedOuter)
+                               if (doFillOuter && !node->mj_MatchedOuter)
                                {
                                        /*
                                         * Generate a fake join tuple with nulls for the inner
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       mergestate->mj_MatchedOuter = true; /* do it only once */
+                                       node->mj_MatchedOuter = true; /* do it only once */
 
                                        ResetExprContext(econtext);
 
-                                       outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                                       outerTupleSlot = node->mj_OuterTupleSlot;
                                        econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = mergestate->mj_NullInnerTupleSlot;
+                                       innerTupleSlot = node->mj_NullInnerTupleSlot;
                                        econtext->ecxt_innertuple = innerTupleSlot;
 
                                        if (ExecQual(otherqual, econtext, false))
@@ -729,12 +727,12 @@ ExecMergeJoin(MergeJoin *node)
 
                                                MJ_printf("ExecMergeJoin: returning fill tuple\n");
 
-                                               result = ExecProject(mergestate->jstate.cs_ProjInfo,
+                                               result = ExecProject(node->js.ps.ps_ProjInfo,
                                                                                         &isDone);
 
                                                if (isDone != ExprEndResult)
                                                {
-                                                       mergestate->jstate.cs_TupFromTlist =
+                                                       node->js.ps.ps_TupFromTlist =
                                                                (isDone == ExprMultipleResult);
                                                        return result;
                                                }
@@ -744,10 +742,10 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * now we get the next outer tuple, if any
                                 */
-                               outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
-                               mergestate->mj_OuterTupleSlot = outerTupleSlot;
+                               outerTupleSlot = ExecProcNode(outerPlan);
+                               node->mj_OuterTupleSlot = outerTupleSlot;
                                MJ_DEBUG_PROC_NODE(outerTupleSlot);
-                               mergestate->mj_MatchedOuter = false;
+                               node->mj_MatchedOuter = false;
 
                                /*
                                 * if the outer tuple is null then we are done with the
@@ -756,21 +754,21 @@ ExecMergeJoin(MergeJoin *node)
                                if (TupIsNull(outerTupleSlot))
                                {
                                        MJ_printf("ExecMergeJoin: end of outer subplan\n");
-                                       innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                                       innerTupleSlot = node->mj_InnerTupleSlot;
                                        if (doFillInner && !TupIsNull(innerTupleSlot))
                                        {
                                                /*
                                                 * Need to emit right-join tuples for remaining
                                                 * inner tuples.
                                                 */
-                                               mergestate->mj_JoinState = EXEC_MJ_ENDOUTER;
+                                               node->mj_JoinState = EXEC_MJ_ENDOUTER;
                                                break;
                                        }
                                        /* Otherwise we're done. */
                                        return NULL;
                                }
 
-                               mergestate->mj_JoinState = EXEC_MJ_TESTOUTER;
+                               node->mj_JoinState = EXEC_MJ_TESTOUTER;
                                break;
 
                                /*--------------------------------------------------------
@@ -816,9 +814,9 @@ ExecMergeJoin(MergeJoin *node)
                                 */
                                ResetExprContext(econtext);
 
-                               outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                               outerTupleSlot = node->mj_OuterTupleSlot;
                                econtext->ecxt_outertuple = outerTupleSlot;
-                               innerTupleSlot = mergestate->mj_MarkedTupleSlot;
+                               innerTupleSlot = node->mj_MarkedTupleSlot;
                                econtext->ecxt_innertuple = innerTupleSlot;
 
                                qualResult = ExecQual(mergeclauses, econtext, false);
@@ -843,7 +841,7 @@ ExecMergeJoin(MergeJoin *node)
                                         * the extra joinquals.
                                         */
                                        ExecRestrPos(innerPlan);
-                                       mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+                                       node->mj_JoinState = EXEC_MJ_JOINTUPLES;
                                }
                                else
                                {
@@ -862,7 +860,7 @@ ExecMergeJoin(MergeJoin *node)
                                         *      larger than our marked inner tuples.  So we're done.
                                         * ----------------
                                         */
-                                       innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                                       innerTupleSlot = node->mj_InnerTupleSlot;
                                        if (TupIsNull(innerTupleSlot))
                                        {
                                                if (doFillOuter)
@@ -871,7 +869,7 @@ ExecMergeJoin(MergeJoin *node)
                                                         * Need to emit left-join tuples for remaining
                                                         * outer tuples.
                                                         */
-                                                       mergestate->mj_JoinState = EXEC_MJ_ENDINNER;
+                                                       node->mj_JoinState = EXEC_MJ_ENDINNER;
                                                        break;
                                                }
                                                /* Otherwise we're done. */
@@ -879,7 +877,7 @@ ExecMergeJoin(MergeJoin *node)
                                        }
 
                                        /* continue on to skip outer tuples */
-                                       mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
+                                       node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
                                }
                                break;
 
@@ -913,9 +911,9 @@ ExecMergeJoin(MergeJoin *node)
                                 */
                                ResetExprContext(econtext);
 
-                               outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                               outerTupleSlot = node->mj_OuterTupleSlot;
                                econtext->ecxt_outertuple = outerTupleSlot;
-                               innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                               innerTupleSlot = node->mj_InnerTupleSlot;
                                econtext->ecxt_innertuple = innerTupleSlot;
 
                                qualResult = ExecQual(mergeclauses, econtext, false);
@@ -925,13 +923,13 @@ ExecMergeJoin(MergeJoin *node)
                                {
                                        ExecMarkPos(innerPlan);
 
-                                       MarkInnerTuple(innerTupleSlot, mergestate);
+                                       MarkInnerTuple(innerTupleSlot, node);
 
-                                       mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+                                       node->mj_JoinState = EXEC_MJ_JOINTUPLES;
                                        break;
                                }
 
-                               mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
+                               node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
                                break;
 
                        case EXEC_MJ_SKIPOUTER_TEST:
@@ -940,9 +938,9 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * ok, now test the skip qualification
                                 */
-                               outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                               outerTupleSlot = node->mj_OuterTupleSlot;
                                econtext->ecxt_outertuple = outerTupleSlot;
-                               innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                               innerTupleSlot = node->mj_InnerTupleSlot;
                                econtext->ecxt_innertuple = innerTupleSlot;
 
                                compareResult = MergeCompare(mergeclauses,
@@ -957,7 +955,7 @@ ExecMergeJoin(MergeJoin *node)
                                 */
                                if (compareResult)
                                {
-                                       mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;
+                                       node->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;
                                        break;
                                }
 
@@ -973,9 +971,9 @@ ExecMergeJoin(MergeJoin *node)
                                MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
 
                                if (compareResult)
-                                       mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
+                                       node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
                                else
-                                       mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
+                                       node->mj_JoinState = EXEC_MJ_JOINMARK;
                                break;
 
                                /*
@@ -985,20 +983,20 @@ ExecMergeJoin(MergeJoin *node)
                        case EXEC_MJ_SKIPOUTER_ADVANCE:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n");
 
-                               if (doFillOuter && !mergestate->mj_MatchedOuter)
+                               if (doFillOuter && !node->mj_MatchedOuter)
                                {
                                        /*
                                         * Generate a fake join tuple with nulls for the inner
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       mergestate->mj_MatchedOuter = true; /* do it only once */
+                                       node->mj_MatchedOuter = true; /* do it only once */
 
                                        ResetExprContext(econtext);
 
-                                       outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                                       outerTupleSlot = node->mj_OuterTupleSlot;
                                        econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = mergestate->mj_NullInnerTupleSlot;
+                                       innerTupleSlot = node->mj_NullInnerTupleSlot;
                                        econtext->ecxt_innertuple = innerTupleSlot;
 
                                        if (ExecQual(otherqual, econtext, false))
@@ -1013,12 +1011,12 @@ ExecMergeJoin(MergeJoin *node)
 
                                                MJ_printf("ExecMergeJoin: returning fill tuple\n");
 
-                                               result = ExecProject(mergestate->jstate.cs_ProjInfo,
+                                               result = ExecProject(node->js.ps.ps_ProjInfo,
                                                                                         &isDone);
 
                                                if (isDone != ExprEndResult)
                                                {
-                                                       mergestate->jstate.cs_TupFromTlist =
+                                                       node->js.ps.ps_TupFromTlist =
                                                                (isDone == ExprMultipleResult);
                                                        return result;
                                                }
@@ -1028,10 +1026,10 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * now we get the next outer tuple, if any
                                 */
-                               outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
-                               mergestate->mj_OuterTupleSlot = outerTupleSlot;
+                               outerTupleSlot = ExecProcNode(outerPlan);
+                               node->mj_OuterTupleSlot = outerTupleSlot;
                                MJ_DEBUG_PROC_NODE(outerTupleSlot);
-                               mergestate->mj_MatchedOuter = false;
+                               node->mj_MatchedOuter = false;
 
                                /*
                                 * if the outer tuple is null then we are done with the
@@ -1040,14 +1038,14 @@ ExecMergeJoin(MergeJoin *node)
                                if (TupIsNull(outerTupleSlot))
                                {
                                        MJ_printf("ExecMergeJoin: end of outer subplan\n");
-                                       innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                                       innerTupleSlot = node->mj_InnerTupleSlot;
                                        if (doFillInner && !TupIsNull(innerTupleSlot))
                                        {
                                                /*
                                                 * Need to emit right-join tuples for remaining
                                                 * inner tuples.
                                                 */
-                                               mergestate->mj_JoinState = EXEC_MJ_ENDOUTER;
+                                               node->mj_JoinState = EXEC_MJ_ENDOUTER;
                                                break;
                                        }
                                        /* Otherwise we're done. */
@@ -1057,7 +1055,7 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * otherwise test the new tuple against the skip qual.
                                 */
-                               mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
+                               node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
                                break;
 
                                /*-----------------------------------------------------------
@@ -1090,9 +1088,9 @@ ExecMergeJoin(MergeJoin *node)
                                 */
                                ResetExprContext(econtext);
 
-                               outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                               outerTupleSlot = node->mj_OuterTupleSlot;
                                econtext->ecxt_outertuple = outerTupleSlot;
-                               innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                               innerTupleSlot = node->mj_InnerTupleSlot;
                                econtext->ecxt_innertuple = innerTupleSlot;
 
                                qualResult = ExecQual(mergeclauses, econtext, false);
@@ -1102,13 +1100,13 @@ ExecMergeJoin(MergeJoin *node)
                                {
                                        ExecMarkPos(innerPlan);
 
-                                       MarkInnerTuple(innerTupleSlot, mergestate);
+                                       MarkInnerTuple(innerTupleSlot, node);
 
-                                       mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+                                       node->mj_JoinState = EXEC_MJ_JOINTUPLES;
                                        break;
                                }
 
-                               mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
+                               node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
                                break;
 
                        case EXEC_MJ_SKIPINNER_TEST:
@@ -1117,9 +1115,9 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * ok, now test the skip qualification
                                 */
-                               outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                               outerTupleSlot = node->mj_OuterTupleSlot;
                                econtext->ecxt_outertuple = outerTupleSlot;
-                               innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                               innerTupleSlot = node->mj_InnerTupleSlot;
                                econtext->ecxt_innertuple = innerTupleSlot;
 
                                compareResult = MergeCompare(mergeclauses,
@@ -1134,7 +1132,7 @@ ExecMergeJoin(MergeJoin *node)
                                 */
                                if (compareResult)
                                {
-                                       mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
+                                       node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
                                        break;
                                }
 
@@ -1150,9 +1148,9 @@ ExecMergeJoin(MergeJoin *node)
                                MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
 
                                if (compareResult)
-                                       mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
+                                       node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
                                else
-                                       mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
+                                       node->mj_JoinState = EXEC_MJ_JOINMARK;
                                break;
 
                                /*
@@ -1162,20 +1160,20 @@ ExecMergeJoin(MergeJoin *node)
                        case EXEC_MJ_SKIPINNER_ADVANCE:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n");
 
-                               if (doFillInner && !mergestate->mj_MatchedInner)
+                               if (doFillInner && !node->mj_MatchedInner)
                                {
                                        /*
                                         * Generate a fake join tuple with nulls for the outer
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       mergestate->mj_MatchedInner = true; /* do it only once */
+                                       node->mj_MatchedInner = true; /* do it only once */
 
                                        ResetExprContext(econtext);
 
-                                       outerTupleSlot = mergestate->mj_NullOuterTupleSlot;
+                                       outerTupleSlot = node->mj_NullOuterTupleSlot;
                                        econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                                       innerTupleSlot = node->mj_InnerTupleSlot;
                                        econtext->ecxt_innertuple = innerTupleSlot;
 
                                        if (ExecQual(otherqual, econtext, false))
@@ -1190,12 +1188,12 @@ ExecMergeJoin(MergeJoin *node)
 
                                                MJ_printf("ExecMergeJoin: returning fill tuple\n");
 
-                                               result = ExecProject(mergestate->jstate.cs_ProjInfo,
+                                               result = ExecProject(node->js.ps.ps_ProjInfo,
                                                                                         &isDone);
 
                                                if (isDone != ExprEndResult)
                                                {
-                                                       mergestate->jstate.cs_TupFromTlist =
+                                                       node->js.ps.ps_TupFromTlist =
                                                                (isDone == ExprMultipleResult);
                                                        return result;
                                                }
@@ -1205,10 +1203,10 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * now we get the next inner tuple, if any
                                 */
-                               innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
-                               mergestate->mj_InnerTupleSlot = innerTupleSlot;
+                               innerTupleSlot = ExecProcNode(innerPlan);
+                               node->mj_InnerTupleSlot = innerTupleSlot;
                                MJ_DEBUG_PROC_NODE(innerTupleSlot);
-                               mergestate->mj_MatchedInner = false;
+                               node->mj_MatchedInner = false;
 
                                /*
                                 * if the inner tuple is null then we are done with the
@@ -1217,14 +1215,14 @@ ExecMergeJoin(MergeJoin *node)
                                if (TupIsNull(innerTupleSlot))
                                {
                                        MJ_printf("ExecMergeJoin: end of inner subplan\n");
-                                       outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                                       outerTupleSlot = node->mj_OuterTupleSlot;
                                        if (doFillOuter && !TupIsNull(outerTupleSlot))
                                        {
                                                /*
                                                 * Need to emit left-join tuples for remaining
                                                 * outer tuples.
                                                 */
-                                               mergestate->mj_JoinState = EXEC_MJ_ENDINNER;
+                                               node->mj_JoinState = EXEC_MJ_ENDINNER;
                                                break;
                                        }
                                        /* Otherwise we're done. */
@@ -1234,7 +1232,7 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * otherwise test the new tuple against the skip qual.
                                 */
-                               mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
+                               node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
                                break;
 
                                /*
@@ -1247,20 +1245,20 @@ ExecMergeJoin(MergeJoin *node)
 
                                Assert(doFillInner);
 
-                               if (!mergestate->mj_MatchedInner)
+                               if (!node->mj_MatchedInner)
                                {
                                        /*
                                         * Generate a fake join tuple with nulls for the outer
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       mergestate->mj_MatchedInner = true; /* do it only once */
+                                       node->mj_MatchedInner = true; /* do it only once */
 
                                        ResetExprContext(econtext);
 
-                                       outerTupleSlot = mergestate->mj_NullOuterTupleSlot;
+                                       outerTupleSlot = node->mj_NullOuterTupleSlot;
                                        econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = mergestate->mj_InnerTupleSlot;
+                                       innerTupleSlot = node->mj_InnerTupleSlot;
                                        econtext->ecxt_innertuple = innerTupleSlot;
 
                                        if (ExecQual(otherqual, econtext, false))
@@ -1275,12 +1273,12 @@ ExecMergeJoin(MergeJoin *node)
 
                                                MJ_printf("ExecMergeJoin: returning fill tuple\n");
 
-                                               result = ExecProject(mergestate->jstate.cs_ProjInfo,
+                                               result = ExecProject(node->js.ps.ps_ProjInfo,
                                                                                         &isDone);
 
                                                if (isDone != ExprEndResult)
                                                {
-                                                       mergestate->jstate.cs_TupFromTlist =
+                                                       node->js.ps.ps_TupFromTlist =
                                                                (isDone == ExprMultipleResult);
                                                        return result;
                                                }
@@ -1290,10 +1288,10 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * now we get the next inner tuple, if any
                                 */
-                               innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
-                               mergestate->mj_InnerTupleSlot = innerTupleSlot;
+                               innerTupleSlot = ExecProcNode(innerPlan);
+                               node->mj_InnerTupleSlot = innerTupleSlot;
                                MJ_DEBUG_PROC_NODE(innerTupleSlot);
-                               mergestate->mj_MatchedInner = false;
+                               node->mj_MatchedInner = false;
 
                                if (TupIsNull(innerTupleSlot))
                                {
@@ -1314,20 +1312,20 @@ ExecMergeJoin(MergeJoin *node)
 
                                Assert(doFillOuter);
 
-                               if (!mergestate->mj_MatchedOuter)
+                               if (!node->mj_MatchedOuter)
                                {
                                        /*
                                         * Generate a fake join tuple with nulls for the inner
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       mergestate->mj_MatchedOuter = true; /* do it only once */
+                                       node->mj_MatchedOuter = true; /* do it only once */
 
                                        ResetExprContext(econtext);
 
-                                       outerTupleSlot = mergestate->mj_OuterTupleSlot;
+                                       outerTupleSlot = node->mj_OuterTupleSlot;
                                        econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = mergestate->mj_NullInnerTupleSlot;
+                                       innerTupleSlot = node->mj_NullInnerTupleSlot;
                                        econtext->ecxt_innertuple = innerTupleSlot;
 
                                        if (ExecQual(otherqual, econtext, false))
@@ -1342,12 +1340,12 @@ ExecMergeJoin(MergeJoin *node)
 
                                                MJ_printf("ExecMergeJoin: returning fill tuple\n");
 
-                                               result = ExecProject(mergestate->jstate.cs_ProjInfo,
+                                               result = ExecProject(node->js.ps.ps_ProjInfo,
                                                                                         &isDone);
 
                                                if (isDone != ExprEndResult)
                                                {
-                                                       mergestate->jstate.cs_TupFromTlist =
+                                                       node->js.ps.ps_TupFromTlist =
                                                                (isDone == ExprMultipleResult);
                                                        return result;
                                                }
@@ -1357,10 +1355,10 @@ ExecMergeJoin(MergeJoin *node)
                                /*
                                 * now we get the next outer tuple, if any
                                 */
-                               outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
-                               mergestate->mj_OuterTupleSlot = outerTupleSlot;
+                               outerTupleSlot = ExecProcNode(outerPlan);
+                               node->mj_OuterTupleSlot = outerTupleSlot;
                                MJ_DEBUG_PROC_NODE(outerTupleSlot);
-                               mergestate->mj_MatchedOuter = false;
+                               node->mj_MatchedOuter = false;
 
                                if (TupIsNull(outerTupleSlot))
                                {
@@ -1377,7 +1375,7 @@ ExecMergeJoin(MergeJoin *node)
                                 */
                        default:
                                elog(WARNING, "ExecMergeJoin: invalid join state %d, aborting",
-                                        mergestate->mj_JoinState);
+                                        node->mj_JoinState);
                                return NULL;
                }
        }
@@ -1385,14 +1383,10 @@ ExecMergeJoin(MergeJoin *node)
 
 /* ----------------------------------------------------------------
  *             ExecInitMergeJoin
- *
- * old comments
- *             Creates the run-time state information for the node and
- *             sets the relation id to contain relevant decriptors.
  * ----------------------------------------------------------------
  */
-bool
-ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
+MergeJoinState *
+ExecInitMergeJoin(MergeJoin *node, EState *estate)
 {
        MergeJoinState *mergestate;
 
@@ -1400,40 +1394,52 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
                           "initializing node");
 
        /*
-        * assign the node's execution state and get the range table and
-        * direction from it
-        */
-       node->join.plan.state = estate;
-
-       /*
-        * create new merge state for node
+        * create state structure
         */
        mergestate = makeNode(MergeJoinState);
-       node->mergestate = mergestate;
+       mergestate->js.ps.plan = (Plan *) node;
+       mergestate->js.ps.state = estate;
 
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &mergestate->jstate);
+       ExecAssignExprContext(estate, &mergestate->js.ps);
+
+       /*
+        * initialize child expressions
+        */
+       mergestate->js.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->join.plan.targetlist,
+                                        (PlanState *) mergestate);
+       mergestate->js.ps.qual = (List *)
+               ExecInitExpr((Node *) node->join.plan.qual,
+                                        (PlanState *) mergestate);
+       mergestate->js.jointype = node->join.jointype;
+       mergestate->js.joinqual = (List *)
+               ExecInitExpr((Node *) node->join.joinqual,
+                                        (PlanState *) mergestate);
+       mergestate->mergeclauses = (List *)
+               ExecInitExpr((Node *) node->mergeclauses,
+                                        (PlanState *) mergestate);
 
        /*
-        * initialize subplans
+        * initialize child nodes
         */
-       ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);
-       ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);
+       outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate);
+       innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate);
 
 #define MERGEJOIN_NSLOTS 4
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &mergestate->jstate);
+       ExecInitResultTupleSlot(estate, &mergestate->js.ps);
 
        mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);
        ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
-                                                 ExecGetTupType(innerPlan((Plan *) node)),
+                                                 ExecGetTupType(innerPlanState(mergestate)),
                                                  false);
 
        switch (node->join.jointype)
@@ -1443,12 +1449,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
                case JOIN_LEFT:
                        mergestate->mj_NullInnerTupleSlot =
                                ExecInitNullTupleSlot(estate,
-                                                          ExecGetTupType(innerPlan((Plan *) node)));
+                                                          ExecGetTupType(innerPlanState(mergestate)));
                        break;
                case JOIN_RIGHT:
                        mergestate->mj_NullOuterTupleSlot =
                                ExecInitNullTupleSlot(estate,
-                                                          ExecGetTupType(outerPlan((Plan *) node)));
+                                                          ExecGetTupType(outerPlanState(mergestate)));
 
                        /*
                         * Can't handle right or full join with non-nil extra
@@ -1460,10 +1466,10 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
                case JOIN_FULL:
                        mergestate->mj_NullOuterTupleSlot =
                                ExecInitNullTupleSlot(estate,
-                                                          ExecGetTupType(outerPlan((Plan *) node)));
+                                                          ExecGetTupType(outerPlanState(mergestate)));
                        mergestate->mj_NullInnerTupleSlot =
                                ExecInitNullTupleSlot(estate,
-                                                          ExecGetTupType(innerPlan((Plan *) node)));
+                                                          ExecGetTupType(innerPlanState(mergestate)));
 
                        /*
                         * Can't handle right or full join with non-nil extra
@@ -1480,8 +1486,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
        /*
         * initialize tuple type and projection info
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &mergestate->jstate);
-       ExecAssignProjectionInfo((Plan *) node, &mergestate->jstate);
+       ExecAssignResultTypeFromTL(&mergestate->js.ps);
+       ExecAssignProjectionInfo(&mergestate->js.ps);
 
        /*
         * form merge skip qualifications
@@ -1500,7 +1506,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
         * initialize join state
         */
        mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
-       mergestate->jstate.cs_TupFromTlist = false;
+       mergestate->js.ps.ps_TupFromTlist = false;
        mergestate->mj_MatchedOuter = false;
        mergestate->mj_MatchedInner = false;
        mergestate->mj_OuterTupleSlot = NULL;
@@ -1512,7 +1518,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
        MJ1_printf("ExecInitMergeJoin: %s\n",
                           "node initialized");
 
-       return TRUE;
+       return mergestate;
 }
 
 int
@@ -1531,65 +1537,52 @@ ExecCountSlotsMergeJoin(MergeJoin *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndMergeJoin(MergeJoin *node)
+ExecEndMergeJoin(MergeJoinState *node)
 {
-       MergeJoinState *mergestate;
-
        MJ1_printf("ExecEndMergeJoin: %s\n",
                           "ending node processing");
 
        /*
-        * get state information from the node
-        */
-       mergestate = node->mergestate;
-
-       /*
         * Free the projection info and the scan attribute info
-        *
-        * Note: we don't ExecFreeResultType(mergestate) because the rule manager
-        * depends on the tupType returned by ExecMain().  So for now, this is
-        * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&mergestate->jstate);
-       ExecFreeExprContext(&mergestate->jstate);
+       ExecFreeProjectionInfo(&node->js.ps);
+       ExecFreeExprContext(&node->js.ps);
 
        /*
         * shut down the subplans
         */
-       ExecEndNode((Plan *) innerPlan((Plan *) node), (Plan *) node);
-       ExecEndNode((Plan *) outerPlan((Plan *) node), (Plan *) node);
+       ExecEndNode(innerPlanState(node));
+       ExecEndNode(outerPlanState(node));
 
        /*
         * clean out the tuple table
         */
-       ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);
-       ExecClearTuple(mergestate->mj_MarkedTupleSlot);
+       ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
+       ExecClearTuple(node->mj_MarkedTupleSlot);
 
        MJ1_printf("ExecEndMergeJoin: %s\n",
                           "node processing ended");
 }
 
 void
-ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt)
 {
-       MergeJoinState *mergestate = node->mergestate;
-
-       ExecClearTuple(mergestate->mj_MarkedTupleSlot);
+       ExecClearTuple(node->mj_MarkedTupleSlot);
 
-       mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
-       mergestate->jstate.cs_TupFromTlist = false;
-       mergestate->mj_MatchedOuter = false;
-       mergestate->mj_MatchedInner = false;
-       mergestate->mj_OuterTupleSlot = NULL;
-       mergestate->mj_InnerTupleSlot = NULL;
+       node->mj_JoinState = EXEC_MJ_INITIALIZE;
+       node->js.ps.ps_TupFromTlist = false;
+       node->mj_MatchedOuter = false;
+       node->mj_MatchedInner = false;
+       node->mj_OuterTupleSlot = NULL;
+       node->mj_InnerTupleSlot = NULL;
 
        /*
         * if chgParam of subnodes is not null then plans will be re-scanned
         * by first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
-       if (((Plan *) node)->righttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+       if (((PlanState *) node)->righttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->righttree, exprCtxt);
 
 }
index 2bd2693..ae2061a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.26 2002/06/20 20:29:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.27 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecNestLoop(NestLoop *node)
+ExecNestLoop(NestLoopState *node)
 {
-       NestLoopState *nlstate;
-       Plan       *innerPlan;
-       Plan       *outerPlan;
+       PlanState  *innerPlan;
+       PlanState  *outerPlan;
        TupleTableSlot *outerTupleSlot;
        TupleTableSlot *innerTupleSlot;
        List       *joinqual;
@@ -73,17 +72,16 @@ ExecNestLoop(NestLoop *node)
         */
        ENL1_printf("getting info from node");
 
-       nlstate = node->nlstate;
-       joinqual = node->join.joinqual;
-       otherqual = node->join.plan.qual;
-       outerPlan = outerPlan((Plan *) node);
-       innerPlan = innerPlan((Plan *) node);
-       econtext = nlstate->jstate.cs_ExprContext;
+       joinqual = node->js.joinqual;
+       otherqual = node->js.ps.qual;
+       outerPlan = outerPlanState(node);
+       innerPlan = innerPlanState(node);
+       econtext = node->js.ps.ps_ExprContext;
 
        /*
         * get the current outer tuple
         */
-       outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot;
+       outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
        econtext->ecxt_outertuple = outerTupleSlot;
 
        /*
@@ -91,16 +89,16 @@ ExecNestLoop(NestLoop *node)
         * join tuple (because there is a function-returning-set in the
         * projection expressions).  If so, try to project another one.
         */
-       if (nlstate->jstate.cs_TupFromTlist)
+       if (node->js.ps.ps_TupFromTlist)
        {
                TupleTableSlot *result;
                ExprDoneCond isDone;
 
-               result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone);
+               result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
                if (isDone == ExprMultipleResult)
                        return result;
                /* Done with that source tuple... */
-               nlstate->jstate.cs_TupFromTlist = false;
+               node->js.ps.ps_TupFromTlist = false;
        }
 
        /*
@@ -122,10 +120,10 @@ ExecNestLoop(NestLoop *node)
                 * If we don't have an outer tuple, get the next one and reset the
                 * inner scan.
                 */
-               if (nlstate->nl_NeedNewOuter)
+               if (node->nl_NeedNewOuter)
                {
                        ENL1_printf("getting new outer tuple");
-                       outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
+                       outerTupleSlot = ExecProcNode(outerPlan);
 
                        /*
                         * if there are no more outer tuples, then the join is
@@ -138,10 +136,10 @@ ExecNestLoop(NestLoop *node)
                        }
 
                        ENL1_printf("saving new outer tuple information");
-                       nlstate->jstate.cs_OuterTupleSlot = outerTupleSlot;
+                       node->js.ps.ps_OuterTupleSlot = outerTupleSlot;
                        econtext->ecxt_outertuple = outerTupleSlot;
-                       nlstate->nl_NeedNewOuter = false;
-                       nlstate->nl_MatchedOuter = false;
+                       node->nl_NeedNewOuter = false;
+                       node->nl_MatchedOuter = false;
 
                        /*
                         * now rescan the inner plan
@@ -153,7 +151,7 @@ ExecNestLoop(NestLoop *node)
                         * outer tuple (e.g. in index scans), that's why we pass our
                         * expr context.
                         */
-                       ExecReScan(innerPlan, econtext, (Plan *) node);
+                       ExecReScan(innerPlan, econtext);
                }
 
                /*
@@ -161,17 +159,17 @@ ExecNestLoop(NestLoop *node)
                 */
                ENL1_printf("getting new inner tuple");
 
-               innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
+               innerTupleSlot = ExecProcNode(innerPlan);
                econtext->ecxt_innertuple = innerTupleSlot;
 
                if (TupIsNull(innerTupleSlot))
                {
                        ENL1_printf("no inner tuple, need new outer tuple");
 
-                       nlstate->nl_NeedNewOuter = true;
+                       node->nl_NeedNewOuter = true;
 
-                       if (!nlstate->nl_MatchedOuter &&
-                               node->join.jointype == JOIN_LEFT)
+                       if (!node->nl_MatchedOuter &&
+                               node->js.jointype == JOIN_LEFT)
                        {
                                /*
                                 * We are doing an outer join and there were no join
@@ -179,7 +177,7 @@ ExecNestLoop(NestLoop *node)
                                 * tuple with nulls for the inner tuple, and return it if
                                 * it passes the non-join quals.
                                 */
-                               econtext->ecxt_innertuple = nlstate->nl_NullInnerTupleSlot;
+                               econtext->ecxt_innertuple = node->nl_NullInnerTupleSlot;
 
                                ENL1_printf("testing qualification for outer-join tuple");
 
@@ -195,11 +193,11 @@ ExecNestLoop(NestLoop *node)
 
                                        ENL1_printf("qualification succeeded, projecting tuple");
 
-                                       result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone);
+                                       result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
 
                                        if (isDone != ExprEndResult)
                                        {
-                                               nlstate->jstate.cs_TupFromTlist =
+                                               node->js.ps.ps_TupFromTlist =
                                                        (isDone == ExprMultipleResult);
                                                return result;
                                        }
@@ -224,7 +222,7 @@ ExecNestLoop(NestLoop *node)
 
                if (ExecQual(joinqual, econtext, false))
                {
-                       nlstate->nl_MatchedOuter = true;
+                       node->nl_MatchedOuter = true;
 
                        if (otherqual == NIL || ExecQual(otherqual, econtext, false))
                        {
@@ -238,11 +236,11 @@ ExecNestLoop(NestLoop *node)
 
                                ENL1_printf("qualification succeeded, projecting tuple");
 
-                               result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone);
+                               result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
 
                                if (isDone != ExprEndResult)
                                {
-                                       nlstate->jstate.cs_TupFromTlist =
+                                       node->js.ps.ps_TupFromTlist =
                                                (isDone == ExprMultipleResult);
                                        return result;
                                }
@@ -260,14 +258,10 @@ ExecNestLoop(NestLoop *node)
 
 /* ----------------------------------------------------------------
  *             ExecInitNestLoop
- *
- *             Creates the run-time state information for the nestloop node
- *             produced by the planner and initailizes inner and outer relations
- *             (child nodes).
  * ----------------------------------------------------------------
  */
-bool
-ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
+NestLoopState *
+ExecInitNestLoop(NestLoop *node, EState *estate)
 {
        NestLoopState *nlstate;
 
@@ -275,35 +269,45 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
                           "initializing node");
 
        /*
-        * assign execution state to node
-        */
-       node->join.plan.state = estate;
-
-       /*
-        * create new nest loop state
+        * create state structure
         */
        nlstate = makeNode(NestLoopState);
-       node->nlstate = nlstate;
+       nlstate->js.ps.plan = (Plan *) node;
+       nlstate->js.ps.state = estate;
 
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &nlstate->jstate);
+       ExecAssignExprContext(estate, &nlstate->js.ps);
 
        /*
-        * now initialize children
+        * initialize child expressions
         */
-       ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);
-       ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);
+       nlstate->js.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->join.plan.targetlist,
+                                        (PlanState *) nlstate);
+       nlstate->js.ps.qual = (List *)
+               ExecInitExpr((Node *) node->join.plan.qual,
+                                        (PlanState *) nlstate);
+       nlstate->js.jointype = node->join.jointype;
+       nlstate->js.joinqual = (List *)
+               ExecInitExpr((Node *) node->join.joinqual,
+                                        (PlanState *) nlstate);
+
+       /*
+        * initialize child nodes
+        */
+       outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate);
+       innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate);
 
 #define NESTLOOP_NSLOTS 2
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &nlstate->jstate);
+       ExecInitResultTupleSlot(estate, &nlstate->js.ps);
 
        switch (node->join.jointype)
        {
@@ -312,7 +316,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
                case JOIN_LEFT:
                        nlstate->nl_NullInnerTupleSlot =
                                ExecInitNullTupleSlot(estate,
-                                                          ExecGetTupType(innerPlan((Plan *) node)));
+                                                          ExecGetTupType(innerPlanState(nlstate)));
                        break;
                default:
                        elog(ERROR, "ExecInitNestLoop: unsupported join type %d",
@@ -322,20 +326,21 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
        /*
         * initialize tuple type and projection info
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate);
-       ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate);
+       ExecAssignResultTypeFromTL(&nlstate->js.ps);
+       ExecAssignProjectionInfo(&nlstate->js.ps);
 
        /*
         * finally, wipe the current outer tuple clean.
         */
-       nlstate->jstate.cs_OuterTupleSlot = NULL;
-       nlstate->jstate.cs_TupFromTlist = false;
+       nlstate->js.ps.ps_OuterTupleSlot = NULL;
+       nlstate->js.ps.ps_TupFromTlist = false;
        nlstate->nl_NeedNewOuter = true;
        nlstate->nl_MatchedOuter = false;
 
        NL1_printf("ExecInitNestLoop: %s\n",
                           "node initialized");
-       return TRUE;
+
+       return nlstate;
 }
 
 int
@@ -353,38 +358,27 @@ ExecCountSlotsNestLoop(NestLoop *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndNestLoop(NestLoop *node)
+ExecEndNestLoop(NestLoopState *node)
 {
-       NestLoopState *nlstate;
-
        NL1_printf("ExecEndNestLoop: %s\n",
                           "ending node processing");
 
        /*
-        * get info from the node
-        */
-       nlstate = node->nlstate;
-
-       /*
         * Free the projection info
-        *
-        * Note: we don't ExecFreeResultType(nlstate) because the rule manager
-        * depends on the tupType returned by ExecMain().  So for now, this is
-        * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&nlstate->jstate);
-       ExecFreeExprContext(&nlstate->jstate);
+       ExecFreeProjectionInfo(&node->js.ps);
+       ExecFreeExprContext(&node->js.ps);
 
        /*
         * close down subplans
         */
-       ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
-       ExecEndNode(innerPlan((Plan *) node), (Plan *) node);
+       ExecEndNode(outerPlanState(node));
+       ExecEndNode(innerPlanState(node));
 
        /*
         * clean out the tuple table
         */
-       ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot);
+       ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
 
        NL1_printf("ExecEndNestLoop: %s\n",
                           "node processing ended");
@@ -395,10 +389,9 @@ ExecEndNestLoop(NestLoop *node)
  * ----------------------------------------------------------------
  */
 void
-ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt)
 {
-       NestLoopState *nlstate = node->nlstate;
-       Plan       *outerPlan = outerPlan((Plan *) node);
+       PlanState   *outerPlan = outerPlanState(node);
 
        /*
         * If outerPlan->chgParam is not null then plan will be automatically
@@ -408,11 +401,11 @@ ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent)
         * run-time keys...
         */
        if (outerPlan->chgParam == NULL)
-               ExecReScan(outerPlan, exprCtxt, (Plan *) node);
+               ExecReScan(outerPlan, exprCtxt);
 
        /* let outerPlan to free its result tuple ... */
-       nlstate->jstate.cs_OuterTupleSlot = NULL;
-       nlstate->jstate.cs_TupFromTlist = false;
-       nlstate->nl_NeedNewOuter = true;
-       nlstate->nl_MatchedOuter = false;
+       node->js.ps.ps_OuterTupleSlot = NULL;
+       node->js.ps.ps_TupFromTlist = false;
+       node->nl_NeedNewOuter = true;
+       node->nl_MatchedOuter = false;
 }
index d9d1608..f14fd01 100644 (file)
@@ -34,7 +34,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.21 2002/06/20 20:29:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.22 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecResult(Result *node)
+ExecResult(ResultState *node)
 {
-       ResultState *resstate;
        TupleTableSlot *outerTupleSlot;
        TupleTableSlot *resultSlot;
-       Plan       *outerPlan;
+       PlanState   *outerPlan;
        ExprContext *econtext;
        ExprDoneCond isDone;
 
-       /*
-        * initialize the result node's state
-        */
-       resstate = node->resstate;
-       econtext = resstate->cstate.cs_ExprContext;
+       econtext = node->ps.ps_ExprContext;
 
        /*
         * check constant qualifications like (2 > 1), if not already done
         */
-       if (resstate->rs_checkqual)
+       if (node->rs_checkqual)
        {
                bool            qualResult = ExecQual((List *) node->resconstantqual,
                                                                                  econtext,
                                                                                  false);
 
-               resstate->rs_checkqual = false;
-               if (qualResult == false)
+               node->rs_checkqual = false;
+               if (!qualResult)
                {
-                       resstate->rs_done = true;
+                       node->rs_done = true;
                        return NULL;
                }
        }
@@ -97,13 +92,13 @@ ExecResult(Result *node)
         * scan tuple (because there is a function-returning-set in the
         * projection expressions).  If so, try to project another one.
         */
-       if (resstate->cstate.cs_TupFromTlist)
+       if (node->ps.ps_TupFromTlist)
        {
-               resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone);
+               resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
                if (isDone == ExprMultipleResult)
                        return resultSlot;
                /* Done with that source tuple... */
-               resstate->cstate.cs_TupFromTlist = false;
+               node->ps.ps_TupFromTlist = false;
        }
 
        /*
@@ -119,9 +114,9 @@ ExecResult(Result *node)
         * called, OR that we failed the constant qual check. Either way, now
         * we are through.
         */
-       while (!resstate->rs_done)
+       while (!node->rs_done)
        {
-               outerPlan = outerPlan(node);
+               outerPlan = outerPlanState(node);
 
                if (outerPlan != NULL)
                {
@@ -129,12 +124,12 @@ ExecResult(Result *node)
                         * retrieve tuples from the outer plan until there are no
                         * more.
                         */
-                       outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
+                       outerTupleSlot = ExecProcNode(outerPlan);
 
                        if (TupIsNull(outerTupleSlot))
                                return NULL;
 
-                       resstate->cstate.cs_OuterTupleSlot = outerTupleSlot;
+                       node->ps.ps_OuterTupleSlot = outerTupleSlot;
 
                        /*
                         * XXX gross hack. use outer tuple as scan tuple for
@@ -149,7 +144,7 @@ ExecResult(Result *node)
                         * if we don't have an outer plan, then we are just generating
                         * the results from a constant target list.  Do it only once.
                         */
-                       resstate->rs_done = true;
+                       node->rs_done = true;
                }
 
                /*
@@ -157,11 +152,11 @@ ExecResult(Result *node)
                 * unless the projection produces an empty set, in which case we
                 * must loop back to see if there are more outerPlan tuples.
                 */
-               resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone);
+               resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
 
                if (isDone != ExprEndResult)
                {
-                       resstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult);
+                       node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
                        return resultSlot;
                }
        }
@@ -177,42 +172,51 @@ ExecResult(Result *node)
  *             (child nodes).
  * ----------------------------------------------------------------
  */
-bool
-ExecInitResult(Result *node, EState *estate, Plan *parent)
+ResultState *
+ExecInitResult(Result *node, EState *estate)
 {
        ResultState *resstate;
 
        /*
-        * assign execution state to node
-        */
-       node->plan.state = estate;
-
-       /*
-        * create new ResultState for node
+        * create state structure
         */
        resstate = makeNode(ResultState);
+       resstate->ps.plan = (Plan *) node;
+       resstate->ps.state = estate;
+
        resstate->rs_done = false;
        resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
-       node->resstate = resstate;
 
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &resstate->cstate);
+       ExecAssignExprContext(estate, &resstate->ps);
 
 #define RESULT_NSLOTS 1
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &resstate->cstate);
+       ExecInitResultTupleSlot(estate, &resstate->ps);
 
        /*
-        * then initialize children
+        * initialize child expressions
         */
-       ExecInitNode(outerPlan(node), estate, (Plan *) node);
+       resstate->ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->plan.targetlist,
+                                        (PlanState *) resstate);
+       resstate->ps.qual = (List *)
+               ExecInitExpr((Node *) node->plan.qual,
+                                        (PlanState *) resstate);
+       resstate->resconstantqual = ExecInitExpr(node->resconstantqual,
+                                                                                        (PlanState *) resstate);
+
+       /*
+        * initialize child nodes
+        */
+       outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate);
 
        /*
         * we don't use inner plan
@@ -222,10 +226,10 @@ ExecInitResult(Result *node, EState *estate, Plan *parent)
        /*
         * initialize tuple type and projection info
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate);
-       ExecAssignProjectionInfo((Plan *) node, &resstate->cstate);
+       ExecAssignResultTypeFromTL(&resstate->ps);
+       ExecAssignProjectionInfo(&resstate->ps);
 
-       return TRUE;
+       return resstate;
 }
 
 int
@@ -241,49 +245,37 @@ ExecCountSlotsResult(Result *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndResult(Result *node)
+ExecEndResult(ResultState *node)
 {
-       ResultState *resstate;
-
-       resstate = node->resstate;
-
        /*
         * Free the projection info
-        *
-        * Note: we don't ExecFreeResultType(resstate) because the rule manager
-        * depends on the tupType returned by ExecMain().  So for now, this is
-        * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&resstate->cstate);
-       ExecFreeExprContext(&resstate->cstate);
+       ExecFreeProjectionInfo(&node->ps);
+       ExecFreeExprContext(&node->ps);
 
        /*
-        * shut down subplans
+        * clean out the tuple table
         */
-       ExecEndNode(outerPlan(node), (Plan *) node);
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
 
        /*
-        * clean out the tuple table
+        * shut down subplans
         */
-       ExecClearTuple(resstate->cstate.cs_ResultTupleSlot);
-       pfree(resstate);
-       node->resstate = NULL;          /* XXX - new for us - er1p */
+       ExecEndNode(outerPlanState(node));
 }
 
 void
-ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanResult(ResultState *node, ExprContext *exprCtxt)
 {
-       ResultState *resstate = node->resstate;
-
-       resstate->rs_done = false;
-       resstate->cstate.cs_TupFromTlist = false;
-       resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
+       node->rs_done = false;
+       node->ps.ps_TupFromTlist = false;
+       node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
 
        /*
         * if chgParam of subnode is not null then plan will be re-scanned by
         * first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree &&
-               ((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree &&
+               ((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 }
index b6848d6..e19098f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.38 2002/11/30 05:21:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.39 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,9 +29,8 @@
 #include "executor/nodeSeqscan.h"
 #include "parser/parsetree.h"
 
-static Oid InitScanRelation(SeqScan *node, EState *estate,
-                                CommonScanState *scanstate);
-static TupleTableSlot *SeqNext(SeqScan *node);
+static void InitScanRelation(SeqScanState *node, EState *estate);
+static TupleTableSlot *SeqNext(SeqScanState *node);
 
 /* ----------------------------------------------------------------
  *                                             Scan Support
@@ -44,11 +43,11 @@ static TupleTableSlot *SeqNext(SeqScan *node);
  * ----------------------------------------------------------------
  */
 static TupleTableSlot *
-SeqNext(SeqScan *node)
+SeqNext(SeqScanState *node)
 {
        HeapTuple       tuple;
        HeapScanDesc scandesc;
-       CommonScanState *scanstate;
+       Index           scanrelid;
        EState     *estate;
        ScanDirection direction;
        TupleTableSlot *slot;
@@ -56,11 +55,11 @@ SeqNext(SeqScan *node)
        /*
         * get information from the estate and scan state
         */
-       estate = node->plan.state;
-       scanstate = node->scanstate;
-       scandesc = scanstate->css_currentScanDesc;
+       estate = node->ps.state;
+       scandesc = node->ss_currentScanDesc;
+       scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
        direction = estate->es_direction;
-       slot = scanstate->css_ScanTupleSlot;
+       slot = node->ss_ScanTupleSlot;
 
        /*
         * Check if we are evaluating PlanQual for tuple of this relation.
@@ -69,13 +68,13 @@ SeqNext(SeqScan *node)
         * switching in Init/ReScan plan...
         */
        if (estate->es_evTuple != NULL &&
-               estate->es_evTuple[node->scanrelid - 1] != NULL)
+               estate->es_evTuple[scanrelid - 1] != NULL)
        {
                ExecClearTuple(slot);
-               if (estate->es_evTupleNull[node->scanrelid - 1])
+               if (estate->es_evTupleNull[scanrelid - 1])
                        return slot;            /* return empty slot */
 
-               ExecStoreTuple(estate->es_evTuple[node->scanrelid - 1],
+               ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
                                           slot, InvalidBuffer, false);
 
                /*
@@ -85,7 +84,7 @@ SeqNext(SeqScan *node)
                 */
 
                /* Flag for the next call that no more tuples */
-               estate->es_evTupleNull[node->scanrelid - 1] = true;
+               estate->es_evTupleNull[scanrelid - 1] = true;
                return (slot);
        }
 
@@ -124,12 +123,12 @@ SeqNext(SeqScan *node)
  */
 
 TupleTableSlot *
-ExecSeqScan(SeqScan *node)
+ExecSeqScan(SeqScanState *node)
 {
        /*
         * use SeqNext as access method
         */
-       return ExecScan(node, (ExecScanAccessMtd) SeqNext);
+       return ExecScan((ScanState *) node, (ExecScanAccessMtd) SeqNext);
 }
 
 /* ----------------------------------------------------------------
@@ -139,9 +138,8 @@ ExecSeqScan(SeqScan *node)
  *             subplans of scans.
  * ----------------------------------------------------------------
  */
-static Oid
-InitScanRelation(SeqScan *node, EState *estate,
-                                CommonScanState *scanstate)
+static void
+InitScanRelation(SeqScanState *node, EState *estate)
 {
        Index           relid;
        List       *rangeTable;
@@ -156,7 +154,7 @@ InitScanRelation(SeqScan *node, EState *estate,
         *
         * We acquire AccessShareLock for the duration of the scan.
         */
-       relid = node->scanrelid;
+       relid = ((SeqScan *) node->ps.plan)->scanrelid;
        rangeTable = estate->es_range_table;
        rtentry = rt_fetch(relid, rangeTable);
        reloid = rtentry->relid;
@@ -168,12 +166,10 @@ InitScanRelation(SeqScan *node, EState *estate,
                                                                         0,
                                                                         NULL);
 
-       scanstate->css_currentRelation = currentRelation;
-       scanstate->css_currentScanDesc = currentScanDesc;
+       node->ss_currentRelation = currentRelation;
+       node->ss_currentScanDesc = currentScanDesc;
 
-       ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
-
-       return reloid;
+       ExecAssignScanType(node, RelationGetDescr(currentRelation), false);
 }
 
 
@@ -181,59 +177,64 @@ InitScanRelation(SeqScan *node, EState *estate,
  *             ExecInitSeqScan
  * ----------------------------------------------------------------
  */
-bool
-ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
+SeqScanState *
+ExecInitSeqScan(SeqScan *node, EState *estate)
 {
-       CommonScanState *scanstate;
-       Oid                     reloid;
+       SeqScanState *scanstate;
 
        /*
         * Once upon a time it was possible to have an outerPlan of a SeqScan,
         * but not any more.
         */
-       Assert(outerPlan((Plan *) node) == NULL);
-       Assert(innerPlan((Plan *) node) == NULL);
-
-       /*
-        * assign the node's execution state
-        */
-       node->plan.state = estate;
+       Assert(outerPlan(node) == NULL);
+       Assert(innerPlan(node) == NULL);
 
        /*
-        * create new CommonScanState for node
+        * create state structure
         */
-       scanstate = makeNode(CommonScanState);
-       node->scanstate = scanstate;
+       scanstate = makeNode(SeqScanState);
+       scanstate->ps.plan = (Plan *) node;
+       scanstate->ps.state = estate;
 
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &scanstate->cstate);
+       ExecAssignExprContext(estate, &scanstate->ps);
+
+       /*
+        * initialize child expressions
+        */
+       scanstate->ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->plan.targetlist,
+                                        (PlanState *) scanstate);
+       scanstate->ps.qual = (List *)
+               ExecInitExpr((Node *) node->plan.qual,
+                                        (PlanState *) scanstate);
 
 #define SEQSCAN_NSLOTS 2
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &scanstate->cstate);
+       ExecInitResultTupleSlot(estate, &scanstate->ps);
        ExecInitScanTupleSlot(estate, scanstate);
 
        /*
         * initialize scan relation
         */
-       reloid = InitScanRelation(node, estate, scanstate);
+       InitScanRelation(scanstate, estate);
 
-       scanstate->cstate.cs_TupFromTlist = false;
+       scanstate->ps.ps_TupFromTlist = false;
 
        /*
         * initialize tuple type
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
-       ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
+       ExecAssignResultTypeFromTL(&scanstate->ps);
+       ExecAssignProjectionInfo(&scanstate->ps);
 
-       return TRUE;
+       return scanstate;
 }
 
 int
@@ -251,28 +252,22 @@ ExecCountSlotsSeqScan(SeqScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndSeqScan(SeqScan *node)
+ExecEndSeqScan(SeqScanState *node)
 {
-       CommonScanState *scanstate;
        Relation        relation;
        HeapScanDesc scanDesc;
 
        /*
         * get information from node
         */
-       scanstate = node->scanstate;
-       relation = scanstate->css_currentRelation;
-       scanDesc = scanstate->css_currentScanDesc;
+       relation = node->ss_currentRelation;
+       scanDesc = node->ss_currentScanDesc;
 
        /*
         * Free the projection info and the scan attribute info
-        *
-        * Note: we don't ExecFreeResultType(scanstate) because the rule manager
-        * depends on the tupType returned by ExecMain().  So for now, this is
-        * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&scanstate->cstate);
-       ExecFreeExprContext(&scanstate->cstate);
+       ExecFreeProjectionInfo(&node->ps);
+       ExecFreeExprContext(&node->ps);
 
        /*
         * close heap scan
@@ -280,6 +275,12 @@ ExecEndSeqScan(SeqScan *node)
        heap_endscan(scanDesc);
 
        /*
+        * clean out the tuple table
+        */
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
+       ExecClearTuple(node->ss_ScanTupleSlot);
+
+       /*
         * close the heap relation.
         *
         * Currently, we do not release the AccessShareLock acquired by
@@ -288,12 +289,6 @@ ExecEndSeqScan(SeqScan *node)
         * locking, however.)
         */
        heap_close(relation, NoLock);
-
-       /*
-        * clean out the tuple table
-        */
-       ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
-       ExecClearTuple(scanstate->css_ScanTupleSlot);
 }
 
 /* ----------------------------------------------------------------
@@ -308,24 +303,24 @@ ExecEndSeqScan(SeqScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt)
 {
-       CommonScanState *scanstate;
        EState     *estate;
+       Index           scanrelid;
        HeapScanDesc scan;
 
-       scanstate = node->scanstate;
-       estate = node->plan.state;
+       estate = node->ps.state;
+       scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
 
        /* If this is re-scanning of PlanQual ... */
        if (estate->es_evTuple != NULL &&
-               estate->es_evTuple[node->scanrelid - 1] != NULL)
+               estate->es_evTuple[scanrelid - 1] != NULL)
        {
-               estate->es_evTupleNull[node->scanrelid - 1] = false;
+               estate->es_evTupleNull[scanrelid - 1] = false;
                return;
        }
 
-       scan = scanstate->css_currentScanDesc;
+       scan = node->ss_currentScanDesc;
 
        heap_rescan(scan,                       /* scan desc */
                                NULL);                  /* new scan keys */
@@ -338,13 +333,11 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
  * ----------------------------------------------------------------
  */
 void
-ExecSeqMarkPos(SeqScan *node)
+ExecSeqMarkPos(SeqScanState *node)
 {
-       CommonScanState *scanstate;
        HeapScanDesc scan;
 
-       scanstate = node->scanstate;
-       scan = scanstate->css_currentScanDesc;
+       scan = node->ss_currentScanDesc;
        heap_markpos(scan);
 }
 
@@ -355,12 +348,10 @@ ExecSeqMarkPos(SeqScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecSeqRestrPos(SeqScan *node)
+ExecSeqRestrPos(SeqScanState *node)
 {
-       CommonScanState *scanstate;
        HeapScanDesc scan;
 
-       scanstate = node->scanstate;
-       scan = scanstate->css_currentScanDesc;
+       scan = node->ss_currentScanDesc;
        heap_restrpos(scan);
 }
index 3d1cf2c..a81a4a2 100644 (file)
@@ -21,7 +21,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.6 2002/06/20 20:29:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.7 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * ----------------------------------------------------------------
  */
 TupleTableSlot *                               /* return: a tuple or NULL */
-ExecSetOp(SetOp *node)
+ExecSetOp(SetOpState *node)
 {
-       SetOpState *setopstate;
+       SetOp      *plannode = (SetOp *) node->ps.plan;
        TupleTableSlot *resultTupleSlot;
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
        TupleDesc       tupDesc;
 
        /*
         * get information from the node
         */
-       setopstate = node->setopstate;
-       outerPlan = outerPlan((Plan *) node);
-       resultTupleSlot = setopstate->cstate.cs_ResultTupleSlot;
-       tupDesc = ExecGetResultType(&setopstate->cstate);
+       outerPlan = outerPlanState(node);
+       resultTupleSlot = node->ps.ps_ResultTupleSlot;
+       tupDesc = ExecGetResultType(&node->ps);
 
        /*
         * If the previously-returned tuple needs to be returned more than
         * once, keep returning it.
         */
-       if (setopstate->numOutput > 0)
+       if (node->numOutput > 0)
        {
-               setopstate->numOutput--;
+               node->numOutput--;
                return resultTupleSlot;
        }
 
@@ -88,15 +87,15 @@ ExecSetOp(SetOp *node)
                /*
                 * fetch a tuple from the outer subplan, unless we already did.
                 */
-               if (setopstate->cstate.cs_OuterTupleSlot == NULL &&
-                       !setopstate->subplan_done)
+               if (node->ps.ps_OuterTupleSlot == NULL &&
+                       !node->subplan_done)
                {
-                       setopstate->cstate.cs_OuterTupleSlot =
-                               ExecProcNode(outerPlan, (Plan *) node);
-                       if (TupIsNull(setopstate->cstate.cs_OuterTupleSlot))
-                               setopstate->subplan_done = true;
+                       node->ps.ps_OuterTupleSlot =
+                               ExecProcNode(outerPlan);
+                       if (TupIsNull(node->ps.ps_OuterTupleSlot))
+                               node->subplan_done = true;
                }
-               inputTupleSlot = setopstate->cstate.cs_OuterTupleSlot;
+               inputTupleSlot = node->ps.ps_OuterTupleSlot;
 
                if (TupIsNull(resultTupleSlot))
                {
@@ -104,18 +103,18 @@ ExecSetOp(SetOp *node)
                         * First of group: save a copy in result slot, and reset
                         * duplicate-counters for new group.
                         */
-                       if (setopstate->subplan_done)
+                       if (node->subplan_done)
                                return NULL;    /* no more tuples */
                        ExecStoreTuple(heap_copytuple(inputTupleSlot->val),
                                                   resultTupleSlot,
                                                   InvalidBuffer,
                                                   true);               /* free copied tuple at
                                                                                 * ExecClearTuple */
-                       setopstate->numLeft = 0;
-                       setopstate->numRight = 0;
+                       node->numLeft = 0;
+                       node->numRight = 0;
                        endOfGroup = false;
                }
-               else if (setopstate->subplan_done)
+               else if (node->subplan_done)
                {
                        /*
                         * Reached end of input, so finish processing final group
@@ -131,9 +130,9 @@ ExecSetOp(SetOp *node)
                        if (execTuplesMatch(inputTupleSlot->val,
                                                                resultTupleSlot->val,
                                                                tupDesc,
-                                                               node->numCols, node->dupColIdx,
-                                                               setopstate->eqfunctions,
-                                                               setopstate->tempContext))
+                                                               plannode->numCols, plannode->dupColIdx,
+                                                               node->eqfunctions,
+                                                               node->tempContext))
                                endOfGroup = false;
                        else
                                endOfGroup = true;
@@ -146,37 +145,37 @@ ExecSetOp(SetOp *node)
                         * Decide how many copies (if any) to emit.  This logic is
                         * straight from the SQL92 specification.
                         */
-                       switch (node->cmd)
+                       switch (plannode->cmd)
                        {
                                case SETOPCMD_INTERSECT:
-                                       if (setopstate->numLeft > 0 && setopstate->numRight > 0)
-                                               setopstate->numOutput = 1;
+                                       if (node->numLeft > 0 && node->numRight > 0)
+                                               node->numOutput = 1;
                                        else
-                                               setopstate->numOutput = 0;
+                                               node->numOutput = 0;
                                        break;
                                case SETOPCMD_INTERSECT_ALL:
-                                       setopstate->numOutput =
-                                               (setopstate->numLeft < setopstate->numRight) ?
-                                               setopstate->numLeft : setopstate->numRight;
+                                       node->numOutput =
+                                               (node->numLeft < node->numRight) ?
+                                               node->numLeft : node->numRight;
                                        break;
                                case SETOPCMD_EXCEPT:
-                                       if (setopstate->numLeft > 0 && setopstate->numRight == 0)
-                                               setopstate->numOutput = 1;
+                                       if (node->numLeft > 0 && node->numRight == 0)
+                                               node->numOutput = 1;
                                        else
-                                               setopstate->numOutput = 0;
+                                               node->numOutput = 0;
                                        break;
                                case SETOPCMD_EXCEPT_ALL:
-                                       setopstate->numOutput =
-                                               (setopstate->numLeft < setopstate->numRight) ?
-                                               0 : (setopstate->numLeft - setopstate->numRight);
+                                       node->numOutput =
+                                               (node->numLeft < node->numRight) ?
+                                               0 : (node->numLeft - node->numRight);
                                        break;
                                default:
                                        elog(ERROR, "ExecSetOp: bogus command code %d",
-                                                (int) node->cmd);
+                                                (int) plannode->cmd);
                                        break;
                        }
                        /* Fall out of for-loop if we have tuples to emit */
-                       if (setopstate->numOutput > 0)
+                       if (node->numOutput > 0)
                                break;
                        /* Else flag that we have no current tuple, and loop around */
                        ExecClearTuple(resultTupleSlot);
@@ -191,16 +190,16 @@ ExecSetOp(SetOp *node)
                        bool            isNull;
 
                        flag = DatumGetInt32(heap_getattr(inputTupleSlot->val,
-                                                                                         node->flagColIdx,
+                                                                                         plannode->flagColIdx,
                                                                                          tupDesc,
                                                                                          &isNull));
                        Assert(!isNull);
                        if (flag)
-                               setopstate->numRight++;
+                               node->numRight++;
                        else
-                               setopstate->numLeft++;
+                               node->numLeft++;
                        /* Set flag to fetch a new input tuple, and loop around */
-                       setopstate->cstate.cs_OuterTupleSlot = NULL;
+                       node->ps.ps_OuterTupleSlot = NULL;
                }
        }
 
@@ -208,8 +207,8 @@ ExecSetOp(SetOp *node)
         * If we fall out of loop, then we need to emit at least one copy of
         * resultTuple.
         */
-       Assert(setopstate->numOutput > 0);
-       setopstate->numOutput--;
+       Assert(node->numOutput > 0);
+       node->numOutput--;
        return resultTupleSlot;
 }
 
@@ -220,23 +219,19 @@ ExecSetOp(SetOp *node)
  *             the node's subplan.
  * ----------------------------------------------------------------
  */
-bool                                                   /* return: initialization status */
-ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
+SetOpState *
+ExecInitSetOp(SetOp *node, EState *estate)
 {
        SetOpState *setopstate;
-       Plan       *outerPlan;
-
-       /*
-        * assign execution state to node
-        */
-       node->plan.state = estate;
 
        /*
-        * create new SetOpState for node
+        * create state structure
         */
        setopstate = makeNode(SetOpState);
-       node->setopstate = setopstate;
-       setopstate->cstate.cs_OuterTupleSlot = NULL;
+       setopstate->ps.plan = (Plan *) node;
+       setopstate->ps.state = estate;
+
+       setopstate->ps.ps_OuterTupleSlot = NULL;
        setopstate->subplan_done = false;
        setopstate->numOutput = 0;
 
@@ -259,30 +254,29 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
        /*
         * Tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &setopstate->cstate);
+       ExecInitResultTupleSlot(estate, &setopstate->ps);
 
        /*
         * then initialize outer plan
         */
-       outerPlan = outerPlan((Plan *) node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
+       outerPlanState(setopstate) = ExecInitNode(outerPlan(node), estate);
 
        /*
         * setop nodes do no projections, so initialize projection info for
         * this node appropriately
         */
-       ExecAssignResultTypeFromOuterPlan((Plan *) node, &setopstate->cstate);
-       setopstate->cstate.cs_ProjInfo = NULL;
+       ExecAssignResultTypeFromOuterPlan(&setopstate->ps);
+       setopstate->ps.ps_ProjInfo = NULL;
 
        /*
         * Precompute fmgr lookup data for inner loop
         */
        setopstate->eqfunctions =
-               execTuplesMatchPrepare(ExecGetResultType(&setopstate->cstate),
+               execTuplesMatchPrepare(ExecGetResultType(&setopstate->ps),
                                                           node->numCols,
                                                           node->dupColIdx);
 
-       return TRUE;
+       return setopstate;
 }
 
 int
@@ -301,34 +295,30 @@ ExecCountSlotsSetOp(SetOp *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndSetOp(SetOp *node)
+ExecEndSetOp(SetOpState *node)
 {
-       SetOpState *setopstate = node->setopstate;
-
-       ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
+       /* clean up tuple table */
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
+       node->ps.ps_OuterTupleSlot = NULL;
 
-       MemoryContextDelete(setopstate->tempContext);
+       ExecEndNode(outerPlanState(node));
 
-       /* clean up tuple table */
-       ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot);
-       setopstate->cstate.cs_OuterTupleSlot = NULL;
+       MemoryContextDelete(node->tempContext);
 }
 
 
 void
-ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt)
 {
-       SetOpState *setopstate = node->setopstate;
-
-       ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot);
-       setopstate->cstate.cs_OuterTupleSlot = NULL;
-       setopstate->subplan_done = false;
-       setopstate->numOutput = 0;
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
+       node->ps.ps_OuterTupleSlot = NULL;
+       node->subplan_done = false;
+       node->numOutput = 0;
 
        /*
         * if chgParam of subnode is not null then plan will be re-scanned by
         * first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+       if (((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 }
index 05f3642..e1b4db7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.40 2002/11/13 00:39:47 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.41 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -88,10 +88,9 @@ ExtractSortKeys(Sort *sortnode,
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecSort(Sort *node)
+ExecSort(SortState *node)
 {
        EState     *estate;
-       SortState  *sortstate;
        ScanDirection dir;
        Tuplesortstate *tuplesortstate;
        HeapTuple       heapTuple;
@@ -104,10 +103,9 @@ ExecSort(Sort *node)
        SO1_printf("ExecSort: %s\n",
                           "entering routine");
 
-       sortstate = node->sortstate;
-       estate = node->plan.state;
+       estate = node->ss.ps.state;
        dir = estate->es_direction;
-       tuplesortstate = (Tuplesortstate *) sortstate->tuplesortstate;
+       tuplesortstate = (Tuplesortstate *) node->tuplesortstate;
 
        /*
         * If first time through, read all tuples from outer plan and pass
@@ -115,9 +113,10 @@ ExecSort(Sort *node)
         * tuplesort.
         */
 
-       if (!sortstate->sort_Done)
+       if (!node->sort_Done)
        {
-               Plan       *outerNode;
+               Sort       *plannode = (Sort *) node->ss.ps.plan;
+               PlanState  *outerNode;
                TupleDesc       tupDesc;
                Oid                *sortOperators;
                AttrNumber *attNums;
@@ -127,8 +126,7 @@ ExecSort(Sort *node)
 
                /*
                 * Want to scan subplan in the forward direction while creating
-                * the sorted data.  (Does setting my direction actually affect
-                * the subplan?  I bet this is useless code...)
+                * the sorted data.
                 */
                estate->es_direction = ForwardScanDirection;
 
@@ -138,15 +136,15 @@ ExecSort(Sort *node)
                SO1_printf("ExecSort: %s\n",
                                   "calling tuplesort_begin");
 
-               outerNode = outerPlan((Plan *) node);
+               outerNode = outerPlanState(node);
                tupDesc = ExecGetTupType(outerNode);
 
-               ExtractSortKeys(node, &sortOperators, &attNums);
+               ExtractSortKeys(plannode, &sortOperators, &attNums);
 
-               tuplesortstate = tuplesort_begin_heap(tupDesc, node->keycount,
+               tuplesortstate = tuplesort_begin_heap(tupDesc, plannode->keycount,
                                                                                          sortOperators, attNums,
                                                                                          true /* randomAccess */ );
-               sortstate->tuplesortstate = (void *) tuplesortstate;
+               node->tuplesortstate = (void *) tuplesortstate;
 
                pfree(sortOperators);
                pfree(attNums);
@@ -157,7 +155,7 @@ ExecSort(Sort *node)
 
                for (;;)
                {
-                       slot = ExecProcNode(outerNode, (Plan *) node);
+                       slot = ExecProcNode(outerNode);
 
                        if (TupIsNull(slot))
                                break;
@@ -178,12 +176,12 @@ ExecSort(Sort *node)
                /*
                 * make sure the tuple descriptor is up to date (is this needed?)
                 */
-               ExecAssignResultType(&sortstate->csstate.cstate, tupDesc, false);
+               ExecAssignResultType(&node->ss.ps, tupDesc, false);
 
                /*
                 * finally set the sorted flag to true
                 */
-               sortstate->sort_Done = true;
+               node->sort_Done = true;
                SO1_printf("ExecSort: %s\n", "sorting done");
        }
 
@@ -198,7 +196,7 @@ ExecSort(Sort *node)
                                                                           ScanDirectionIsForward(dir),
                                                                           &should_free);
 
-       slot = sortstate->csstate.cstate.cs_ResultTupleSlot;
+       slot = node->ss.ps.ps_ResultTupleSlot;
        return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
 }
 
@@ -209,29 +207,24 @@ ExecSort(Sort *node)
  *             produced by the planner and initailizes its outer subtree.
  * ----------------------------------------------------------------
  */
-bool
-ExecInitSort(Sort *node, EState *estate, Plan *parent)
+SortState *
+ExecInitSort(Sort *node, EState *estate)
 {
        SortState  *sortstate;
-       Plan       *outerPlan;
 
        SO1_printf("ExecInitSort: %s\n",
                           "initializing sort node");
 
        /*
-        * assign the node's execution state
-        */
-       node->plan.state = estate;
-
-       /*
         * create state structure
         */
        sortstate = makeNode(SortState);
+       sortstate->ss.ps.plan = (Plan *) node;
+       sortstate->ss.ps.state = estate;
+
        sortstate->sort_Done = false;
        sortstate->tuplesortstate = NULL;
 
-       node->sortstate = sortstate;
-
        /*
         * Miscellaneous initialization
         *
@@ -246,27 +239,26 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
         *
         * sort nodes only return scan tuples from their sorted relation.
         */
-       ExecInitResultTupleSlot(estate, &sortstate->csstate.cstate);
-       ExecInitScanTupleSlot(estate, &sortstate->csstate);
+       ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
+       ExecInitScanTupleSlot(estate, &sortstate->ss);
 
        /*
         * initializes child nodes
         */
-       outerPlan = outerPlan((Plan *) node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
+       outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate);
 
        /*
         * initialize tuple type.  no need to initialize projection info
         * because this node doesn't do projections.
         */
-       ExecAssignResultTypeFromOuterPlan((Plan *) node, &sortstate->csstate.cstate);
-       ExecAssignScanTypeFromOuterPlan((Plan *) node, &sortstate->csstate);
-       sortstate->csstate.cstate.cs_ProjInfo = NULL;
+       ExecAssignResultTypeFromOuterPlan(&sortstate->ss.ps);
+       ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
+       sortstate->ss.ps.ps_ProjInfo = NULL;
 
        SO1_printf("ExecInitSort: %s\n",
                           "sort node initialized");
 
-       return TRUE;
+       return sortstate;
 }
 
 int
@@ -282,39 +274,27 @@ ExecCountSlotsSort(Sort *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndSort(Sort *node)
+ExecEndSort(SortState *node)
 {
-       SortState  *sortstate;
-       Plan       *outerPlan;
-
-       /*
-        * get info from the sort state
-        */
        SO1_printf("ExecEndSort: %s\n",
                           "shutting down sort node");
 
-       sortstate = node->sortstate;
-
        /*
-        * shut down the subplan
+        * clean out the tuple table
         */
-       outerPlan = outerPlan((Plan *) node);
-       ExecEndNode(outerPlan, (Plan *) node);
+       ExecClearTuple(node->ss.ss_ScanTupleSlot);
 
        /*
-        * clean out the tuple table
+        * shut down the subplan
         */
-       ExecClearTuple(sortstate->csstate.css_ScanTupleSlot);
+       ExecEndNode(outerPlanState(node));
 
        /*
         * Release tuplesort resources
         */
-       if (sortstate->tuplesortstate != NULL)
-               tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate);
-       sortstate->tuplesortstate = NULL;
-
-       pfree(sortstate);
-       node->sortstate = NULL;
+       if (node->tuplesortstate != NULL)
+               tuplesort_end((Tuplesortstate *) node->tuplesortstate);
+       node->tuplesortstate = NULL;
 
        SO1_printf("ExecEndSort: %s\n",
                           "sort node shutdown");
@@ -327,17 +307,15 @@ ExecEndSort(Sort *node)
  * ----------------------------------------------------------------
  */
 void
-ExecSortMarkPos(Sort *node)
+ExecSortMarkPos(SortState *node)
 {
-       SortState  *sortstate = node->sortstate;
-
        /*
         * if we haven't sorted yet, just return
         */
-       if (!sortstate->sort_Done)
+       if (!node->sort_Done)
                return;
 
-       tuplesort_markpos((Tuplesortstate *) sortstate->tuplesortstate);
+       tuplesort_markpos((Tuplesortstate *) node->tuplesortstate);
 }
 
 /* ----------------------------------------------------------------
@@ -347,36 +325,32 @@ ExecSortMarkPos(Sort *node)
  * ----------------------------------------------------------------
  */
 void
-ExecSortRestrPos(Sort *node)
+ExecSortRestrPos(SortState *node)
 {
-       SortState  *sortstate = node->sortstate;
-
        /*
         * if we haven't sorted yet, just return.
         */
-       if (!sortstate->sort_Done)
+       if (!node->sort_Done)
                return;
 
        /*
         * restore the scan to the previously marked position
         */
-       tuplesort_restorepos((Tuplesortstate *) sortstate->tuplesortstate);
+       tuplesort_restorepos((Tuplesortstate *) node->tuplesortstate);
 }
 
 void
-ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanSort(SortState *node, ExprContext *exprCtxt)
 {
-       SortState  *sortstate = node->sortstate;
-
        /*
         * If we haven't sorted yet, just return. If outerplan' chgParam is
         * not NULL then it will be re-scanned by ExecProcNode, else - no
         * reason to re-scan it at all.
         */
-       if (!sortstate->sort_Done)
+       if (!node->sort_Done)
                return;
 
-       ExecClearTuple(sortstate->csstate.cstate.cs_ResultTupleSlot);
+       ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
        /*
         * If subnode is to be rescanned then we forget previous sort results;
@@ -384,12 +358,12 @@ ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent)
         *
         * Otherwise we can just rewind and rescan the sorted output.
         */
-       if (((Plan *) node)->lefttree->chgParam != NULL)
+       if (((PlanState *) node)->lefttree->chgParam != NULL)
        {
-               sortstate->sort_Done = false;
-               tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate);
-               sortstate->tuplesortstate = NULL;
+               node->sort_Done = false;
+               tuplesort_end((Tuplesortstate *) node->tuplesortstate);
+               node->tuplesortstate = NULL;
        }
        else
-               tuplesort_rescan((Tuplesortstate *) sortstate->tuplesortstate);
+               tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);
 }
index 73ff637..195634c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.34 2002/11/26 03:01:57 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.35 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 /* ----------------------------------------------------------------
  *             ExecSubPlan(node)
- *
  * ----------------------------------------------------------------
  */
 Datum
-ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
+ExecSubPlan(SubPlanState *node, List *pvar,
+                       ExprContext *econtext, bool *isNull)
 {
-       Plan       *plan = node->plan;
-       SubLink    *sublink = node->sublink;
+       PlanState  *planstate = node->planstate;
+       SubPlan    *subplan = (SubPlan *) node->ps.plan;
+       SubLink    *sublink = subplan->sublink;
        SubLinkType subLinkType = sublink->subLinkType;
        bool            useor = sublink->useor;
        MemoryContext oldcontext;
@@ -49,15 +50,15 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
         */
        oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
 
-       if (node->setParam != NIL)
+       if (subplan->setParam != NIL)
                elog(ERROR, "ExecSubPlan: can't set parent params from subquery");
 
        /*
         * Set Params of this plan from parent plan correlation Vars
         */
-       if (node->parParam != NIL)
+       if (subplan->parParam != NIL)
        {
-               foreach(lst, node->parParam)
+               foreach(lst, subplan->parParam)
                {
                        ParamExecData *prm;
 
@@ -69,11 +70,12 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
                                                                                                   NULL);
                        pvar = lnext(pvar);
                }
-               plan->chgParam = nconc(plan->chgParam, listCopy(node->parParam));
+               planstate->chgParam = nconc(planstate->chgParam,
+                                                                       listCopy(subplan->parParam));
        }
        Assert(pvar == NIL);
 
-       ExecReScan(plan, NULL, NULL);
+       ExecReScan(planstate, NULL);
 
        /*
         * For all sublink types except EXPR_SUBLINK, the result is boolean as
@@ -96,9 +98,9 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
        result = BoolGetDatum(subLinkType == ALL_SUBLINK);
        *isNull = false;
 
-       for (slot = ExecProcNode(plan, NULL);
+       for (slot = ExecProcNode(planstate);
                 !TupIsNull(slot);
-                slot = ExecProcNode(plan, NULL))
+                slot = ExecProcNode(planstate))
        {
                HeapTuple       tup = slot->val;
                TupleDesc       tdesc = slot->ttc_tupleDescriptor;
@@ -283,13 +285,37 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
 
 /* ----------------------------------------------------------------
  *             ExecInitSubPlan
- *
  * ----------------------------------------------------------------
  */
-bool
-ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
+SubPlanState *
+ExecInitSubPlan(SubPlan *node, EState *estate)
 {
-       EState     *sp_estate = CreateExecutorState();
+       SubPlanState *subplanstate;
+       EState     *sp_estate;
+
+       /*
+        * Do access checking on the rangetable entries in the subquery.
+        * Here, we assume the subquery is a SELECT.
+        */
+       ExecCheckRTPerms(node->rtable, CMD_SELECT);
+
+       /*
+        * create state structure
+        */
+       subplanstate = makeNode(SubPlanState);
+       subplanstate->ps.plan = (Plan *) node;
+       subplanstate->ps.state = estate;
+
+       subplanstate->needShutdown = false;
+       subplanstate->curTuple = NULL;
+
+       /* XXX temporary hack */
+       node->pstate = subplanstate;
+
+       /*
+        * create an EState for the subplan
+        */
+       sp_estate = CreateExecutorState();
 
        sp_estate->es_range_table = node->rtable;
        sp_estate->es_param_list_info = estate->es_param_list_info;
@@ -297,14 +323,14 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
        sp_estate->es_tupleTable =
                ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10);
        sp_estate->es_snapshot = estate->es_snapshot;
+       sp_estate->es_instrument = estate->es_instrument;
 
-       node->needShutdown = false;
-       node->curTuple = NULL;
-
-       if (!ExecInitNode(node->plan, sp_estate, parent))
-               return false;
+       /*
+        * Start up the subplan
+        */
+       subplanstate->planstate = ExecInitNode(node->plan, sp_estate);
 
-       node->needShutdown = true;      /* now we need to shutdown the subplan */
+       subplanstate->needShutdown = true;      /* now we need to shutdown the subplan */
 
        /*
         * If this plan is un-correlated or undirect correlated one and want
@@ -318,7 +344,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
                {
                        ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
 
-                       prm->execPlan = node;
+                       prm->execPlan = subplanstate;
                }
 
                /*
@@ -328,7 +354,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
                 */
        }
 
-       return true;
+       return subplanstate;
 }
 
 /* ----------------------------------------------------------------
@@ -345,10 +371,12 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
  * ----------------------------------------------------------------
  */
 void
-ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
+ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 {
-       Plan       *plan = node->plan;
-       SubLink    *sublink = node->sublink;
+       PlanState  *planstate = node->planstate;
+       SubPlan    *subplan = (SubPlan *) node->ps.plan;
+       SubLink    *sublink = subplan->sublink;
+       EState     *estate = node->ps.state;
        MemoryContext oldcontext;
        TupleTableSlot *slot;
        List       *lst;
@@ -364,12 +392,12 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
                sublink->subLinkType == ALL_SUBLINK)
                elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported");
 
-       if (plan->chgParam != NULL)
-               ExecReScan(plan, NULL, NULL);
+       if (planstate->chgParam != NULL)
+               ExecReScan(planstate, NULL);
 
-       for (slot = ExecProcNode(plan, NULL);
+       for (slot = ExecProcNode(planstate);
                 !TupIsNull(slot);
-                slot = ExecProcNode(plan, NULL))
+                slot = ExecProcNode(planstate))
        {
                HeapTuple       tup = slot->val;
                TupleDesc       tdesc = slot->ttc_tupleDescriptor;
@@ -377,7 +405,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
 
                if (sublink->subLinkType == EXISTS_SUBLINK)
                {
-                       ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]);
+                       ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
 
                        prm->execPlan = NULL;
                        prm->value = BoolGetDatum(true);
@@ -404,9 +432,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
                        heap_freetuple(node->curTuple);
                node->curTuple = tup;
 
-               foreach(lst, node->setParam)
+               foreach(lst, subplan->setParam)
                {
-                       ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);
+                       ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
 
                        prm->execPlan = NULL;
                        prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));
@@ -418,7 +446,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
        {
                if (sublink->subLinkType == EXISTS_SUBLINK)
                {
-                       ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]);
+                       ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
 
                        prm->execPlan = NULL;
                        prm->value = BoolGetDatum(false);
@@ -426,9 +454,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
                }
                else
                {
-                       foreach(lst, node->setParam)
+                       foreach(lst, subplan->setParam)
                        {
-                               ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);
+                               ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
 
                                prm->execPlan = NULL;
                                prm->value = (Datum) 0;
@@ -437,9 +465,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
                }
        }
 
-       if (plan->extParam == NULL) /* un-correlated ... */
+       if (planstate->plan->extParam == NULL) /* un-correlated ... */
        {
-               ExecEndNode(plan, NULL);
+               ExecEndNode(planstate);
                node->needShutdown = false;
        }
 
@@ -451,11 +479,11 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
  * ----------------------------------------------------------------
  */
 void
-ExecEndSubPlan(SubPlan *node)
+ExecEndSubPlan(SubPlanState *node)
 {
        if (node->needShutdown)
        {
-               ExecEndNode(node->plan, NULL);
+               ExecEndNode(node->planstate);
                node->needShutdown = false;
        }
        if (node->curTuple)
@@ -466,33 +494,34 @@ ExecEndSubPlan(SubPlan *node)
 }
 
 void
-ExecReScanSetParamPlan(SubPlan *node, Plan *parent)
+ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
 {
-       Plan       *plan = node->plan;
+       PlanState  *planstate = node->planstate;
+       SubPlan    *subplan = (SubPlan *) node->ps.plan;
+       EState     *estate = node->ps.state;
        List       *lst;
 
-       if (node->parParam != NULL)
+       if (subplan->parParam != NULL)
                elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet");
-       if (node->setParam == NULL)
+       if (subplan->setParam == NULL)
                elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL");
-       if (plan->extParam == NULL)
+       if (planstate->plan->extParam == NULL)
                elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL");
 
        /*
         * Don't actual re-scan: ExecSetParamPlan does re-scan if
-        * node->plan->chgParam is not NULL... ExecReScan (plan, NULL, NULL);
+        * subplan->plan->chgParam is not NULL... ExecReScan (planstate, NULL);
         */
 
        /*
         * Mark this subplan's output parameters as needing recalculation
         */
-       foreach(lst, node->setParam)
+       foreach(lst, subplan->setParam)
        {
-               ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);
+               ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
 
                prm->execPlan = node;
        }
 
-       parent->chgParam = nconc(parent->chgParam, listCopy(node->setParam));
-
+       parent->chgParam = nconc(parent->chgParam, listCopy(subplan->setParam));
 }
index 982dd02..ba0ed86 100644 (file)
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.13 2002/06/20 20:29:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,7 +35,7 @@
 #include "parser/parsetree.h"
 #include "tcop/pquery.h"
 
-static TupleTableSlot *SubqueryNext(SubqueryScan *node);
+static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
 
 /* ----------------------------------------------------------------
  *                                             Scan Support
@@ -48,9 +48,8 @@ static TupleTableSlot *SubqueryNext(SubqueryScan *node);
  * ----------------------------------------------------------------
  */
 static TupleTableSlot *
-SubqueryNext(SubqueryScan *node)
+SubqueryNext(SubqueryScanState *node)
 {
-       SubqueryScanState *subquerystate;
        EState     *estate;
        ScanDirection direction;
        TupleTableSlot *slot;
@@ -58,8 +57,7 @@ SubqueryNext(SubqueryScan *node)
        /*
         * get information from the estate and scan state
         */
-       estate = node->scan.plan.state;
-       subquerystate = (SubqueryScanState *) node->scan.scanstate;
+       estate = node->ss.ps.state;
        direction = estate->es_direction;
 
        /*
@@ -70,11 +68,11 @@ SubqueryNext(SubqueryScan *node)
        /*
         * get the next tuple from the sub-query
         */
-       subquerystate->sss_SubEState->es_direction = direction;
+       node->sss_SubEState->es_direction = direction;
 
-       slot = ExecProcNode(node->subplan, (Plan *) node);
+       slot = ExecProcNode(node->subplan);
 
-       subquerystate->csstate.css_ScanTupleSlot = slot;
+       node->ss.ss_ScanTupleSlot = slot;
 
        return slot;
 }
@@ -90,20 +88,20 @@ SubqueryNext(SubqueryScan *node)
  */
 
 TupleTableSlot *
-ExecSubqueryScan(SubqueryScan *node)
+ExecSubqueryScan(SubqueryScanState *node)
 {
        /*
         * use SubqueryNext as access method
         */
-       return ExecScan(&node->scan, (ExecScanAccessMtd) SubqueryNext);
+       return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext);
 }
 
 /* ----------------------------------------------------------------
  *             ExecInitSubqueryScan
  * ----------------------------------------------------------------
  */
-bool
-ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
+SubqueryScanState *
+ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
 {
        SubqueryScanState *subquerystate;
        RangeTblEntry *rte;
@@ -112,33 +110,39 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
        /*
         * SubqueryScan should not have any "normal" children.
         */
-       Assert(outerPlan((Plan *) node) == NULL);
-       Assert(innerPlan((Plan *) node) == NULL);
+       Assert(outerPlan(node) == NULL);
+       Assert(innerPlan(node) == NULL);
 
        /*
-        * assign the node's execution state
-        */
-       node->scan.plan.state = estate;
-
-       /*
-        * create new SubqueryScanState for node
+        * create state structure
         */
        subquerystate = makeNode(SubqueryScanState);
-       node->scan.scanstate = (CommonScanState *) subquerystate;
+       subquerystate->ss.ps.plan = (Plan *) node;
+       subquerystate->ss.ps.state = estate;
 
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
-       ExecAssignExprContext(estate, &subquerystate->csstate.cstate);
+       ExecAssignExprContext(estate, &subquerystate->ss.ps);
+
+       /*
+        * initialize child expressions
+        */
+       subquerystate->ss.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->scan.plan.targetlist,
+                                        (PlanState *) subquerystate);
+       subquerystate->ss.ps.qual = (List *)
+               ExecInitExpr((Node *) node->scan.plan.qual,
+                                        (PlanState *) subquerystate);
 
 #define SUBQUERYSCAN_NSLOTS 1
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &subquerystate->csstate.cstate);
+       ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
 
        /*
         * initialize subquery
@@ -157,20 +161,20 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
        sp_estate->es_tupleTable =
                ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
        sp_estate->es_snapshot = estate->es_snapshot;
+       sp_estate->es_instrument = estate->es_instrument;
 
-       if (!ExecInitNode(node->subplan, sp_estate, (Plan *) node))
-               return false;
+       subquerystate->subplan = ExecInitNode(node->subplan, sp_estate);
 
-       subquerystate->csstate.css_ScanTupleSlot = NULL;
-       subquerystate->csstate.cstate.cs_TupFromTlist = false;
+       subquerystate->ss.ss_ScanTupleSlot = NULL;
+       subquerystate->ss.ps.ps_TupFromTlist = false;
 
        /*
         * initialize tuple type
         */
-       ExecAssignResultTypeFromTL((Plan *) node, &subquerystate->csstate.cstate);
-       ExecAssignProjectionInfo((Plan *) node, &subquerystate->csstate.cstate);
+       ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
+       ExecAssignProjectionInfo(&subquerystate->ss.ps);
 
-       return TRUE;
+       return subquerystate;
 }
 
 int
@@ -191,42 +195,31 @@ ExecCountSlotsSubqueryScan(SubqueryScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndSubqueryScan(SubqueryScan *node)
+ExecEndSubqueryScan(SubqueryScanState *node)
 {
-       SubqueryScanState *subquerystate;
-
        /*
-        * get information from node
+        * Free the projection info and the scan attribute info
         */
-       subquerystate = (SubqueryScanState *) node->scan.scanstate;
+       ExecFreeProjectionInfo(&node->ss.ps);
+       ExecFreeExprContext(&node->ss.ps);
 
        /*
-        * Free the projection info and the scan attribute info
-        *
-        * Note: we don't ExecFreeResultType(subquerystate) because the rule
-        * manager depends on the tupType returned by ExecMain().  So for now,
-        * this is freed at end-transaction time.  -cim 6/2/91
+        * clean out the upper tuple table
         */
-       ExecFreeProjectionInfo(&subquerystate->csstate.cstate);
-       ExecFreeExprContext(&subquerystate->csstate.cstate);
+       ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
        /*
         * close down subquery
         */
-       ExecEndNode(node->subplan, (Plan *) node);
+       ExecEndNode(node->subplan);
 
        /*
         * clean up subquery's tuple table
         */
-       subquerystate->csstate.css_ScanTupleSlot = NULL;
-       ExecDropTupleTable(subquerystate->sss_SubEState->es_tupleTable, true);
+       node->ss.ss_ScanTupleSlot = NULL;
+       ExecDropTupleTable(node->sss_SubEState->es_tupleTable, true);
 
        /* XXX we seem to be leaking the sub-EState... */
-
-       /*
-        * clean out the upper tuple table
-        */
-       ExecClearTuple(subquerystate->csstate.cstate.cs_ResultTupleSlot);
 }
 
 /* ----------------------------------------------------------------
@@ -236,27 +229,25 @@ ExecEndSubqueryScan(SubqueryScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecSubqueryReScan(SubqueryScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
 {
-       SubqueryScanState *subquerystate;
        EState     *estate;
 
-       subquerystate = (SubqueryScanState *) node->scan.scanstate;
-       estate = node->scan.plan.state;
+       estate = node->ss.ps.state;
 
        /*
         * ExecReScan doesn't know about my subplan, so I have to do
         * changed-parameter signaling myself.
         */
-       if (node->scan.plan.chgParam != NULL)
-               SetChangedParamList(node->subplan, node->scan.plan.chgParam);
+       if (node->ss.ps.chgParam != NULL)
+               SetChangedParamList(node->subplan, node->ss.ps.chgParam);
 
        /*
         * if chgParam of subnode is not null then plan will be re-scanned by
         * first ExecProcNode.
         */
        if (node->subplan->chgParam == NULL)
-               ExecReScan(node->subplan, NULL, (Plan *) node);
+               ExecReScan(node->subplan, NULL);
 
-       subquerystate->csstate.css_ScanTupleSlot = NULL;
+       node->ss.ss_ScanTupleSlot = NULL;
 }
index 0fb7c6d..53b3c26 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.27 2002/11/30 05:21:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.28 2002/12/05 15:50:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,7 @@
 #include "parser/parsetree.h"
 
 static int     TidListCreate(List *, ExprContext *, ItemPointerData[]);
-static TupleTableSlot *TidNext(TidScan *node);
+static TupleTableSlot *TidNext(TidScanState *node);
 
 static int
 TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[])
@@ -65,19 +65,17 @@ TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[])
  * ----------------------------------------------------------------
  */
 static TupleTableSlot *
-TidNext(TidScan *node)
+TidNext(TidScanState *node)
 {
        EState     *estate;
-       CommonScanState *scanstate;
-       TidScanState *tidstate;
        ScanDirection direction;
        Snapshot        snapshot;
        Relation        heapRelation;
        HeapTuple       tuple;
        TupleTableSlot *slot;
+       Index           scanrelid;
        Buffer          buffer = InvalidBuffer;
        int                     numTids;
-
        bool            bBackward;
        int                     tidNumber;
        ItemPointerData *tidList;
@@ -85,15 +83,14 @@ TidNext(TidScan *node)
        /*
         * extract necessary information from tid scan node
         */
-       estate = node->scan.plan.state;
+       estate = node->ss.ps.state;
        direction = estate->es_direction;
        snapshot = estate->es_snapshot;
-       scanstate = node->scan.scanstate;
-       tidstate = node->tidstate;
-       heapRelation = scanstate->css_currentRelation;
-       numTids = tidstate->tss_NumTids;
-       tidList = tidstate->tss_TidList;
-       slot = scanstate->css_ScanTupleSlot;
+       heapRelation = node->ss.ss_currentRelation;
+       numTids = node->tss_NumTids;
+       tidList = node->tss_TidList;
+       slot = node->ss.ss_ScanTupleSlot;
+       scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid;
 
        /*
         * Check if we are evaluating PlanQual for tuple of this relation.
@@ -102,10 +99,10 @@ TidNext(TidScan *node)
         * switching in Init/ReScan plan...
         */
        if (estate->es_evTuple != NULL &&
-               estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+               estate->es_evTuple[scanrelid - 1] != NULL)
        {
                ExecClearTuple(slot);
-               if (estate->es_evTupleNull[node->scan.scanrelid - 1])
+               if (estate->es_evTupleNull[scanrelid - 1])
                        return slot;            /* return empty slot */
 
                /*
@@ -113,15 +110,15 @@ TidNext(TidScan *node)
                 * list? In runtime-key case this is not certain, is it?
                 */
 
-               ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
+               ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
                                           slot, InvalidBuffer, false);
 
                /* Flag for the next call that no more tuples */
-               estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
+               estate->es_evTupleNull[scanrelid - 1] = true;
                return (slot);
        }
 
-       tuple = &(tidstate->tss_htup);
+       tuple = &(node->tss_htup);
 
        /*
         * ok, now that we have what we need, fetch an tid tuple. if scanning
@@ -131,26 +128,26 @@ TidNext(TidScan *node)
        bBackward = ScanDirectionIsBackward(direction);
        if (bBackward)
        {
-               tidNumber = numTids - tidstate->tss_TidPtr - 1;
+               tidNumber = numTids - node->tss_TidPtr - 1;
                if (tidNumber < 0)
                {
                        tidNumber = 0;
-                       tidstate->tss_TidPtr = numTids - 1;
+                       node->tss_TidPtr = numTids - 1;
                }
        }
        else
        {
-               if ((tidNumber = tidstate->tss_TidPtr) < 0)
+               if ((tidNumber = node->tss_TidPtr) < 0)
                {
                        tidNumber = 0;
-                       tidstate->tss_TidPtr = 0;
+                       node->tss_TidPtr = 0;
                }
        }
        while (tidNumber < numTids)
        {
                bool            slot_is_valid = false;
 
-               tuple->t_self = tidList[tidstate->tss_TidPtr];
+               tuple->t_self = tidList[node->tss_TidPtr];
                if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL))
                {
                        bool            prev_matches = false;
@@ -181,7 +178,7 @@ TidNext(TidScan *node)
                         * do this by passing the tuple through ExecQual and look for
                         * failure with all previous qualifications.
                         */
-                       for (prev_tid = 0; prev_tid < tidstate->tss_TidPtr;
+                       for (prev_tid = 0; prev_tid < node->tss_TidPtr;
                                 prev_tid++)
                        {
                                if (ItemPointerEquals(&tidList[prev_tid], &tuple->t_self))
@@ -197,9 +194,9 @@ TidNext(TidScan *node)
                }
                tidNumber++;
                if (bBackward)
-                       tidstate->tss_TidPtr--;
+                       node->tss_TidPtr--;
                else
-                       tidstate->tss_TidPtr++;
+                       node->tss_TidPtr++;
                if (slot_is_valid)
                        return slot;
        }
@@ -231,12 +228,12 @@ TidNext(TidScan *node)
  * ----------------------------------------------------------------
  */
 TupleTableSlot *
-ExecTidScan(TidScan *node)
+ExecTidScan(TidScanState *node)
 {
        /*
         * use TidNext as access method
         */
-       return ExecScan(&node->scan, (ExecScanAccessMtd) TidNext);
+       return ExecScan(&node->ss, (ExecScanAccessMtd) TidNext);
 }
 
 /* ----------------------------------------------------------------
@@ -244,42 +241,30 @@ ExecTidScan(TidScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecTidReScan(TidScanState *node, ExprContext *exprCtxt)
 {
        EState     *estate;
-       TidScanState *tidstate;
        ItemPointerData *tidList;
+       Index           scanrelid;
 
-       estate = node->scan.plan.state;
-       tidstate = node->tidstate;
-       tidList = tidstate->tss_TidList;
+       estate = node->ss.ps.state;
+       tidList = node->tss_TidList;
+       scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid;
 
        /* If we are being passed an outer tuple, save it for runtime key calc */
        if (exprCtxt != NULL)
-               node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
+               node->ss.ps.ps_ExprContext->ecxt_outertuple =
                        exprCtxt->ecxt_outertuple;
 
-       /* do runtime calc of target TIDs, if needed */
-       if (node->needRescan)
-               tidstate->tss_NumTids =
-                       TidListCreate(node->tideval,
-                                                 node->scan.scanstate->cstate.cs_ExprContext,
-                                                 tidList);
-
        /* If this is re-scanning of PlanQual ... */
        if (estate->es_evTuple != NULL &&
-               estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+               estate->es_evTuple[scanrelid - 1] != NULL)
        {
-               estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
+               estate->es_evTupleNull[scanrelid - 1] = false;
                return;
        }
 
-       tidstate->tss_TidPtr = -1;
-
-       /*
-        * perhaps return something meaningful
-        */
-       return;
+       node->tss_TidPtr = -1;
 }
 
 /* ----------------------------------------------------------------
@@ -290,18 +275,13 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
  * ----------------------------------------------------------------
  */
 void
-ExecEndTidScan(TidScan *node)
+ExecEndTidScan(TidScanState *node)
 {
-       CommonScanState *scanstate;
-       TidScanState *tidstate;
-
        /*
         * extract information from the node
         */
-       scanstate = node->scan.scanstate;
-       tidstate = node->tidstate;
-       if (tidstate && tidstate->tss_TidList)
-               pfree(tidstate->tss_TidList);
+       if (node && node->tss_TidList)
+               pfree(node->tss_TidList);
 
        /*
         * Free the projection info and the scan attribute info
@@ -310,8 +290,14 @@ ExecEndTidScan(TidScan *node)
         * depends on the tupType returned by ExecMain().  So for now, this is
         * freed at end-transaction time.  -cim 6/2/91
         */
-       ExecFreeProjectionInfo(&scanstate->cstate);
-       ExecFreeExprContext(&scanstate->cstate);
+       ExecFreeProjectionInfo(&node->ss.ps);
+       ExecFreeExprContext(&node->ss.ps);
+
+       /*
+        * clear out tuple table slots
+        */
+       ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+       ExecClearTuple(node->ss.ss_ScanTupleSlot);
 
        /*
         * close the heap relation.
@@ -320,13 +306,7 @@ ExecEndTidScan(TidScan *node)
         * ExecInitTidScan.  This lock should be held till end of transaction.
         * (There is a faction that considers this too much locking, however.)
         */
-       heap_close(scanstate->css_currentRelation, NoLock);
-
-       /*
-        * clear out tuple table slots
-        */
-       ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
-       ExecClearTuple(scanstate->css_ScanTupleSlot);
+       heap_close(node->ss.ss_currentRelation, NoLock);
 }
 
 /* ----------------------------------------------------------------
@@ -337,12 +317,9 @@ ExecEndTidScan(TidScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecTidMarkPos(TidScan *node)
+ExecTidMarkPos(TidScanState *node)
 {
-       TidScanState *tidstate;
-
-       tidstate = node->tidstate;
-       tidstate->tss_MarkTidPtr = tidstate->tss_TidPtr;
+       node->tss_MarkTidPtr = node->tss_TidPtr;
 }
 
 /* ----------------------------------------------------------------
@@ -355,12 +332,9 @@ ExecTidMarkPos(TidScan *node)
  * ----------------------------------------------------------------
  */
 void
-ExecTidRestrPos(TidScan *node)
+ExecTidRestrPos(TidScanState *node)
 {
-       TidScanState *tidstate;
-
-       tidstate = node->tidstate;
-       tidstate->tss_TidPtr = tidstate->tss_MarkTidPtr;
+       node->tss_TidPtr = node->tss_MarkTidPtr;
 }
 
 /* ----------------------------------------------------------------
@@ -374,11 +348,10 @@ ExecTidRestrPos(TidScan *node)
  *               estate: the execution state initialized in InitPlan.
  * ----------------------------------------------------------------
  */
-bool
-ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
+TidScanState *
+ExecInitTidScan(TidScan *node, EState *estate)
 {
        TidScanState *tidstate;
-       CommonScanState *scanstate;
        ItemPointerData *tidList;
        int                     numTids;
        int                     tidPtr;
@@ -390,56 +363,50 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
        List       *execParam = NIL;
 
        /*
-        * assign execution state to node
+        * create state structure
         */
-       node->scan.plan.state = estate;
+       tidstate = makeNode(TidScanState);
+       tidstate->ss.ps.plan = (Plan *) node;
+       tidstate->ss.ps.state = estate;
 
        /*
-        * Part 1)      initialize scan state
+        * Miscellaneous initialization
         *
-        * create new CommonScanState for node
+        * create expression context for node
         */
-       scanstate = makeNode(CommonScanState);
-       node->scan.scanstate = scanstate;
+       ExecAssignExprContext(estate, &tidstate->ss.ps);
 
        /*
-        * Miscellaneous initialization
-        *
-        * create expression context for node
+        * initialize child expressions
         */
-       ExecAssignExprContext(estate, &scanstate->cstate);
+       tidstate->ss.ps.targetlist = (List *)
+               ExecInitExpr((Node *) node->scan.plan.targetlist,
+                                        (PlanState *) tidstate);
+       tidstate->ss.ps.qual = (List *)
+               ExecInitExpr((Node *) node->scan.plan.qual,
+                                        (PlanState *) tidstate);
 
 #define TIDSCAN_NSLOTS 2
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &scanstate->cstate);
-       ExecInitScanTupleSlot(estate, scanstate);
+       ExecInitResultTupleSlot(estate, &tidstate->ss.ps);
+       ExecInitScanTupleSlot(estate, &tidstate->ss);
 
        /*
         * initialize projection info.  result type comes from scan desc
         * below..
         */
-       ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
-
-       /*
-        * Part 2)      initialize tid scan state
-        *
-        * create new TidScanState for node
-        */
-       tidstate = makeNode(TidScanState);
-       node->tidstate = tidstate;
+       ExecAssignProjectionInfo(&tidstate->ss.ps);
 
        /*
         * get the tid node information
         */
        tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData));
-       numTids = 0;
-       if (!node->needRescan)
-               numTids = TidListCreate(node->tideval,
-                                                               scanstate->cstate.cs_ExprContext,
-                                                               tidList);
+       numTids = TidListCreate(node->tideval,
+                                                       tidstate->ss.ps.ps_ExprContext,
+                                                       tidList);
        tidPtr = -1;
 
        CXT1_printf("ExecInitTidScan: context is %d\n", CurrentMemoryContext);
@@ -465,25 +432,25 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
 
        currentRelation = heap_open(reloid, AccessShareLock);
 
-       scanstate->css_currentRelation = currentRelation;
-       scanstate->css_currentScanDesc = NULL;          /* no heap scan here */
+       tidstate->ss.ss_currentRelation = currentRelation;
+       tidstate->ss.ss_currentScanDesc = NULL;         /* no heap scan here */
 
        /*
         * get the scan type from the relation descriptor.
         */
-       ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
-       ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
+       ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation), false);
+       ExecAssignResultTypeFromTL(&tidstate->ss.ps);
 
        /*
         * if there are some PARAM_EXEC in skankeys then force tid rescan on
         * first scan.
         */
-       ((Plan *) node)->chgParam = execParam;
+       tidstate->ss.ps.chgParam = execParam;
 
        /*
         * all done.
         */
-       return TRUE;
+       return tidstate;
 }
 
 int
index b71403d..88b0806 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.34 2002/06/20 20:29:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.35 2002/12/05 15:50:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,6 @@
  * NOTES
  *             Assumes tuples returned from subplan arrive in
  *             sorted order.
- *
  */
 
 #include "postgres.h"
  * ----------------------------------------------------------------
  */
 TupleTableSlot *                               /* return: a tuple or NULL */
-ExecUnique(Unique *node)
+ExecUnique(UniqueState *node)
 {
-       UniqueState *uniquestate;
+       Unique     *plannode = (Unique *) node->ps.plan;
        TupleTableSlot *resultTupleSlot;
        TupleTableSlot *slot;
-       Plan       *outerPlan;
+       PlanState  *outerPlan;
        TupleDesc       tupDesc;
 
        /*
         * get information from the node
         */
-       uniquestate = node->uniquestate;
-       outerPlan = outerPlan((Plan *) node);
-       resultTupleSlot = uniquestate->cstate.cs_ResultTupleSlot;
-       tupDesc = ExecGetResultType(&uniquestate->cstate);
+       outerPlan = outerPlanState(node);
+       resultTupleSlot = node->ps.ps_ResultTupleSlot;
+       tupDesc = ExecGetResultType(&node->ps);
 
        /*
         * now loop, returning only non-duplicate tuples. We assume that the
@@ -64,14 +62,14 @@ ExecUnique(Unique *node)
                /*
                 * fetch a tuple from the outer subplan
                 */
-               slot = ExecProcNode(outerPlan, (Plan *) node);
+               slot = ExecProcNode(outerPlan);
                if (TupIsNull(slot))
                        return NULL;
 
                /*
                 * Always return the first tuple from the subplan.
                 */
-               if (uniquestate->priorTuple == NULL)
+               if (node->priorTuple == NULL)
                        break;
 
                /*
@@ -79,11 +77,11 @@ ExecUnique(Unique *node)
                 * match.  If so then we loop back and fetch another new tuple
                 * from the subplan.
                 */
-               if (!execTuplesMatch(slot->val, uniquestate->priorTuple,
+               if (!execTuplesMatch(slot->val, node->priorTuple,
                                                         tupDesc,
-                                                        node->numCols, node->uniqColIdx,
-                                                        uniquestate->eqfunctions,
-                                                        uniquestate->tempContext))
+                                                        plannode->numCols, plannode->uniqColIdx,
+                                                        node->eqfunctions,
+                                                        node->tempContext))
                        break;
        }
 
@@ -99,11 +97,11 @@ ExecUnique(Unique *node)
         * handling in execMain.c).  We assume that the caller will no longer
         * be interested in the current tuple after he next calls us.
         */
-       if (uniquestate->priorTuple != NULL)
-               heap_freetuple(uniquestate->priorTuple);
-       uniquestate->priorTuple = heap_copytuple(slot->val);
+       if (node->priorTuple != NULL)
+               heap_freetuple(node->priorTuple);
+       node->priorTuple = heap_copytuple(slot->val);
 
-       ExecStoreTuple(uniquestate->priorTuple,
+       ExecStoreTuple(node->priorTuple,
                                   resultTupleSlot,
                                   InvalidBuffer,
                                   false);              /* tuple does not belong to slot */
@@ -118,22 +116,18 @@ ExecUnique(Unique *node)
  *             the node's subplan.
  * ----------------------------------------------------------------
  */
-bool                                                   /* return: initialization status */
-ExecInitUnique(Unique *node, EState *estate, Plan *parent)
+UniqueState *
+ExecInitUnique(Unique *node, EState *estate)
 {
        UniqueState *uniquestate;
-       Plan       *outerPlan;
 
        /*
-        * assign execution state to node
-        */
-       node->plan.state = estate;
-
-       /*
-        * create new UniqueState for node
+        * create state structure
         */
        uniquestate = makeNode(UniqueState);
-       node->uniquestate = uniquestate;
+       uniquestate->ps.plan = (Plan *) node;
+       uniquestate->ps.state = estate;
+
        uniquestate->priorTuple = NULL;
 
        /*
@@ -155,30 +149,29 @@ ExecInitUnique(Unique *node, EState *estate, Plan *parent)
        /*
         * Tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &uniquestate->cstate);
+       ExecInitResultTupleSlot(estate, &uniquestate->ps);
 
        /*
         * then initialize outer plan
         */
-       outerPlan = outerPlan((Plan *) node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
+       outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate);
 
        /*
         * unique nodes do no projections, so initialize projection info for
         * this node appropriately
         */
-       ExecAssignResultTypeFromOuterPlan((Plan *) node, &uniquestate->cstate);
-       uniquestate->cstate.cs_ProjInfo = NULL;
+       ExecAssignResultTypeFromOuterPlan(&uniquestate->ps);
+       uniquestate->ps.ps_ProjInfo = NULL;
 
        /*
         * Precompute fmgr lookup data for inner loop
         */
        uniquestate->eqfunctions =
-               execTuplesMatchPrepare(ExecGetResultType(&uniquestate->cstate),
+               execTuplesMatchPrepare(ExecGetResultType(&uniquestate->ps),
                                                           node->numCols,
                                                           node->uniqColIdx);
 
-       return TRUE;
+       return uniquestate;
 }
 
 int
@@ -197,41 +190,36 @@ ExecCountSlotsUnique(Unique *node)
  * ----------------------------------------------------------------
  */
 void
-ExecEndUnique(Unique *node)
+ExecEndUnique(UniqueState *node)
 {
-       UniqueState *uniquestate = node->uniquestate;
-
-       ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
-
-       MemoryContextDelete(uniquestate->tempContext);
-
        /* clean up tuple table */
-       ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot);
-       if (uniquestate->priorTuple != NULL)
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
+       if (node->priorTuple != NULL)
        {
-               heap_freetuple(uniquestate->priorTuple);
-               uniquestate->priorTuple = NULL;
+               heap_freetuple(node->priorTuple);
+               node->priorTuple = NULL;
        }
+
+       ExecEndNode(outerPlanState(node));
+
+       MemoryContextDelete(node->tempContext);
 }
 
 
 void
-ExecReScanUnique(Unique *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
 {
-       UniqueState *uniquestate = node->uniquestate;
-
-       ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot);
-       if (uniquestate->priorTuple != NULL)
+       ExecClearTuple(node->ps.ps_ResultTupleSlot);
+       if (node->priorTuple != NULL)
        {
-               heap_freetuple(uniquestate->priorTuple);
-               uniquestate->priorTuple = NULL;
+               heap_freetuple(node->priorTuple);
+               node->priorTuple = NULL;
        }
 
        /*
         * if chgParam of subnode is not null then plan will be re-scanned by
         * first ExecProcNode.
         */
-       if (((Plan *) node)->lefttree->chgParam == NULL)
-               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
-
+       if (((PlanState *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 }
index 6e897e4..147becf 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.78 2002/11/13 00:39:47 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.79 2002/12/05 15:50:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,7 +33,7 @@ static int    _SPI_connected = -1;
 static int     _SPI_curid = -1;
 
 static int     _SPI_execute(char *src, int tcount, _SPI_plan *plan);
-static int     _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount);
+static int     _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount);
 
 static int _SPI_execute_plan(_SPI_plan *plan,
                                  Datum *Values, char *Nulls, int tcount);
@@ -705,9 +705,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
        List       *ptlist = spiplan->ptlist;
        Query      *queryTree;
        Plan       *planTree;
+       ParamListInfo paramLI;
        QueryDesc  *queryDesc;
-       EState     *eState;
-       TupleDesc       attinfo;
        MemoryContext oldcontext;
        Portal          portal;
        char            portalname[64];
@@ -774,28 +773,21 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
        queryTree->into->relname = pstrdup(name);
        queryTree->isBinary = false;
 
-       /* Create the QueryDesc object and the executor state */
-       queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL);
-       eState = CreateExecutorState();
-
-       /* If the plan has parameters, put them into the executor state */
+       /* If the plan has parameters, set them up */
        if (spiplan->nargs > 0)
        {
-               ParamListInfo paramLI;
-
                paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) *
-                                                                                sizeof(ParamListInfoData));
+                                                                                 sizeof(ParamListInfoData));
 
-               eState->es_param_list_info = paramLI;
-               for (k = 0; k < spiplan->nargs; paramLI++, k++)
+               for (k = 0; k < spiplan->nargs; k++)
                {
-                       paramLI->kind = PARAM_NUM;
-                       paramLI->id = k + 1;
-                       paramLI->isnull = (Nulls && Nulls[k] == 'n');
-                       if (paramLI->isnull)
+                       paramLI[k].kind = PARAM_NUM;
+                       paramLI[k].id = k + 1;
+                       paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
+                       if (paramLI[k].isnull)
                        {
                                /* nulls just copy */
-                               paramLI->value = Values[k];
+                               paramLI[k].value = Values[k];
                        }
                        else
                        {
@@ -805,20 +797,24 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
 
                                get_typlenbyval(spiplan->argtypes[k],
                                                                &paramTypLen, &paramTypByVal);
-                               paramLI->value = datumCopy(Values[k],
-                                                                                  paramTypByVal, paramTypLen);
+                               paramLI[k].value = datumCopy(Values[k],
+                                                                                        paramTypByVal, paramTypLen);
                        }
                }
-               paramLI->kind = PARAM_INVALID;
+               paramLI[k].kind = PARAM_INVALID;
        }
        else
-               eState->es_param_list_info = NULL;
+               paramLI = NULL;
+
+       /* Create the QueryDesc object */
+       queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL,
+                                                               paramLI, false);
 
        /* Start the executor */
-       attinfo = ExecutorStart(queryDesc, eState);
+       ExecutorStart(queryDesc);
 
-       /* Put all the objects into the portal */
-       PortalSetQuery(portal, queryDesc, attinfo, eState, PortalCleanup);
+       /* Arrange to shut down the executor if portal is dropped */
+       PortalSetQuery(portal, queryDesc, PortalCleanup);
 
        /* Switch back to the callers memory context */
        MemoryContextSwitchTo(oldcontext);
@@ -1042,7 +1038,6 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
                        Plan       *planTree;
                        bool            canSetResult;
                        QueryDesc  *qdesc;
-                       EState     *state;
 
                        planTree = pg_plan_query(queryTree);
                        plan_list = lappend(plan_list, planTree);
@@ -1089,9 +1084,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
                        else if (plan == NULL)
                        {
                                qdesc = CreateQueryDesc(queryTree, planTree,
-                                                                               canSetResult ? SPI : None, NULL);
-                               state = CreateExecutorState();
-                               res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0);
+                                                                               canSetResult ? SPI : None,
+                                                                               NULL, NULL, false);
+                               res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0);
                                if (res < 0)
                                        return res;
                                CommandCounterIncrement();
@@ -1099,8 +1094,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
                        else
                        {
                                qdesc = CreateQueryDesc(queryTree, planTree,
-                                                                               canSetResult ? SPI : None, NULL);
-                               res = _SPI_pquery(qdesc, NULL, 0);
+                                                                               canSetResult ? SPI : None,
+                                                                               NULL, NULL, false);
+                               res = _SPI_pquery(qdesc, false, 0);
                                if (res < 0)
                                        return res;
                        }
@@ -1152,7 +1148,6 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
                        Plan       *planTree;
                        bool            canSetResult;
                        QueryDesc  *qdesc;
-                       EState     *state;
 
                        planTree = lfirst(plan_list);
                        plan_list = lnext(plan_list);
@@ -1183,30 +1178,31 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
                        }
                        else
                        {
-                               qdesc = CreateQueryDesc(queryTree, planTree,
-                                                                               canSetResult ? SPI : None, NULL);
-                               state = CreateExecutorState();
+                               ParamListInfo paramLI;
+
                                if (nargs > 0)
                                {
-                                       ParamListInfo paramLI;
                                        int                     k;
 
                                        paramLI = (ParamListInfo)
                                                palloc0((nargs + 1) * sizeof(ParamListInfoData));
 
-                                       state->es_param_list_info = paramLI;
-                                       for (k = 0; k < plan->nargs; paramLI++, k++)
+                                       for (k = 0; k < plan->nargs; k++)
                                        {
-                                               paramLI->kind = PARAM_NUM;
-                                               paramLI->id = k + 1;
-                                               paramLI->isnull = (Nulls && Nulls[k] == 'n');
-                                               paramLI->value = Values[k];
+                                               paramLI[k].kind = PARAM_NUM;
+                                               paramLI[k].id = k + 1;
+                                               paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
+                                               paramLI[k].value = Values[k];
                                        }
-                                       paramLI->kind = PARAM_INVALID;
+                                       paramLI[k].kind = PARAM_INVALID;
                                }
                                else
-                                       state->es_param_list_info = NULL;
-                               res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0);
+                                       paramLI = NULL;
+
+                               qdesc = CreateQueryDesc(queryTree, planTree,
+                                                                               canSetResult ? SPI : None,
+                                                                               NULL, paramLI, false);
+                               res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0);
                                if (res < 0)
                                        return res;
                                CommandCounterIncrement();
@@ -1218,7 +1214,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
 }
 
 static int
-_SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
+_SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
 {
        Query      *parseTree = queryDesc->parsetree;
        int                     operation = queryDesc->operation;
@@ -1262,7 +1258,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
                        return SPI_ERROR_OPUNKNOWN;
        }
 
-       if (state == NULL)                      /* plan preparation, don't execute */
+       if (!runit)                                     /* plan preparation, don't execute */
                return res;
 
 #ifdef SPI_EXECUTOR_STATS
@@ -1270,20 +1266,20 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
                ResetUsage();
 #endif
 
-       ExecutorStart(queryDesc, state);
+       ExecutorStart(queryDesc);
 
        /*
         * Don't work currently --- need to rearrange callers so that we
-        * prepare the portal before doing CreateExecutorState() etc. See
+        * prepare the portal before doing ExecutorStart() etc. See
         * pquery.c for the correct order of operations.
         */
        if (isRetrieveIntoPortal)
                elog(FATAL, "SPI_select: retrieve into portal not implemented");
 
-       ExecutorRun(queryDesc, state, ForwardScanDirection, (long) tcount);
+       ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
 
-       _SPI_current->processed = state->es_processed;
-       save_lastoid = state->es_lastoid;
+       _SPI_current->processed = queryDesc->estate->es_processed;
+       save_lastoid = queryDesc->estate->es_lastoid;
 
        if (operation == CMD_SELECT && queryDesc->dest == SPI)
        {
@@ -1291,7 +1287,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
                        elog(FATAL, "SPI_select: # of processed tuples check failed");
        }
 
-       ExecutorEnd(queryDesc, state);
+       ExecutorEnd(queryDesc);
 
 #ifdef SPI_EXECUTOR_STATS
        if (ShowExecutorStats)
@@ -1342,7 +1338,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
        oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
 
        querydesc = PortalGetQueryDesc(portal);
-       estate = PortalGetState(portal);
+       estate = querydesc->estate;
 
        /* Save the queries command destination and set it to SPI (for fetch) */
        /* or None (for move) */
@@ -1357,7 +1353,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
                else
                        direction = ForwardScanDirection;
 
-               ExecutorRun(querydesc, estate, direction, (long) count);
+               ExecutorRun(querydesc, direction, (long) count);
 
                if (estate->es_processed > 0)
                        portal->atStart = false;        /* OK to back up now */
@@ -1371,7 +1367,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
                else
                        direction = BackwardScanDirection;
 
-               ExecutorRun(querydesc, estate, direction, (long) count);
+               ExecutorRun(querydesc, direction, (long) count);
 
                if (estate->es_processed > 0)
                        portal->atEnd = false;          /* OK to go forward now */
index d11b5ed..1fe7efd 100644 (file)
@@ -3,27 +3,28 @@
  * copyfuncs.c
  *       Copy functions for Postgres tree nodes.
  *
- * NOTE: a general convention when copying or comparing plan nodes is
- * that we ignore the executor state subnode.  We do not need to look
- * at it because no current uses of copyObject() or equal() need to
- * deal with already-executing plan trees.     By leaving the state subnodes
- * out, we avoid needing to write copy/compare routines for all the
- * different executor state node types.
+ * NOTE: we currently support copying all node types found in parse and
+ * plan trees.  We do not support copying executor state trees; there
+ * is no need for that, and no point in maintaining all the code that
+ * would be needed.  We also do not support copying Path trees, mainly
+ * because the circular linkages between RelOptInfo and Path nodes can't
+ * be handled easily in a simple depth-first traversal.
  *
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.225 2002/11/30 05:21:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.226 2002/12/05 15:50:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
-#include "optimizer/clauses.h"
-#include "optimizer/planmain.h"
+#include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
+#include "nodes/relation.h"
 #include "utils/datum.h"
 
 
                memcpy(newnode->fldname, from->fldname, _size); \
        } while (0)
 
-/* Special hack for fixing subplan lists of Plan nodes (ick) */
-#define FIX_SUBPLAN_LINKS(subplanfldname, fldname) \
-       do { \
-               if (from->subplanfldname != NIL) \
-                       newnode->subplanfldname = \
-                               nconc(newnode->subplanfldname, \
-                                         pull_subplans((Node *) (newnode->fldname))); \
-       } while (0)
-
 
 /*
  * listCopy
@@ -119,19 +111,13 @@ CopyPlanFields(Plan *from, Plan *newnode)
        COPY_SCALAR_FIELD(total_cost);
        COPY_SCALAR_FIELD(plan_rows);
        COPY_SCALAR_FIELD(plan_width);
-       /* execution state is NOT copied */
        COPY_NODE_FIELD(targetlist);
        COPY_NODE_FIELD(qual);
        COPY_NODE_FIELD(lefttree);
        COPY_NODE_FIELD(righttree);
+       COPY_NODE_FIELD(initPlan);
        COPY_INTLIST_FIELD(extParam);
        COPY_INTLIST_FIELD(locParam);
-       COPY_INTLIST_FIELD(chgParam);
-       COPY_NODE_FIELD(initPlan);
-       /* subPlan list must point to subplans in the new subtree, not the old */
-       newnode->subPlan = NIL;
-       FIX_SUBPLAN_LINKS(subPlan, targetlist);
-       FIX_SUBPLAN_LINKS(subPlan, qual);
        COPY_SCALAR_FIELD(nParamExec);
 }
 
@@ -170,9 +156,6 @@ _copyResult(Result *from)
         */
        COPY_NODE_FIELD(resconstantqual);
 
-       /* subPlan list must point to subplans in the new subtree, not the old */
-       FIX_SUBPLAN_LINKS(plan.subPlan, resconstantqual);
-
        return newnode;
 }
 
@@ -266,10 +249,6 @@ _copyIndexScan(IndexScan *from)
        COPY_NODE_FIELD(indxqualorig);
        COPY_SCALAR_FIELD(indxorderdir);
 
-       /* subPlan list must point to subplans in the new subtree, not the old */
-       FIX_SUBPLAN_LINKS(scan.plan.subPlan, indxqual);
-       FIX_SUBPLAN_LINKS(scan.plan.subPlan, indxqualorig);
-
        return newnode;
 }
 
@@ -289,12 +268,8 @@ _copyTidScan(TidScan *from)
        /*
         * copy remainder of node
         */
-       COPY_SCALAR_FIELD(needRescan);
        COPY_NODE_FIELD(tideval);
 
-       /* subPlan list must point to subplans in the new subtree, not the old */
-       FIX_SUBPLAN_LINKS(scan.plan.subPlan, tideval);
-
        return newnode;
 }
 
@@ -348,9 +323,6 @@ CopyJoinFields(Join *from, Join *newnode)
 
        COPY_SCALAR_FIELD(jointype);
        COPY_NODE_FIELD(joinqual);
-
-       /* subPlan list must point to subplans in the new subtree, not the old */
-       FIX_SUBPLAN_LINKS(plan.subPlan, joinqual);
 }
 
 
@@ -406,9 +378,6 @@ _copyMergeJoin(MergeJoin *from)
         */
        COPY_NODE_FIELD(mergeclauses);
 
-       /* subPlan list must point to subplans in the new subtree, not the old */
-       FIX_SUBPLAN_LINKS(join.plan.subPlan, mergeclauses);
-
        return newnode;
 }
 
@@ -430,9 +399,6 @@ _copyHashJoin(HashJoin *from)
         */
        COPY_NODE_FIELD(hashclauses);
 
-       /* subPlan list must point to subplans in the new subtree, not the old */
-       FIX_SUBPLAN_LINKS(join.plan.subPlan, hashclauses);
-
        return newnode;
 }
 
@@ -531,12 +497,12 @@ _copyUnique(Unique *from)
 }
 
 /*
- * _copySetOp
+ * _copyHash
  */
-static SetOp *
-_copySetOp(SetOp *from)
+static Hash *
+_copyHash(Hash *from)
 {
-       SetOp      *newnode = makeNode(SetOp);
+       Hash       *newnode = makeNode(Hash);
 
        /*
         * copy node superclass fields
@@ -546,21 +512,18 @@ _copySetOp(SetOp *from)
        /*
         * copy remainder of node
         */
-       COPY_SCALAR_FIELD(cmd);
-       COPY_SCALAR_FIELD(numCols);
-       COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
-       COPY_SCALAR_FIELD(flagColIdx);
+       COPY_NODE_FIELD(hashkeys);
 
        return newnode;
 }
 
 /*
- * _copyLimit
+ * _copySetOp
  */
-static Limit *
-_copyLimit(Limit *from)
+static SetOp *
+_copySetOp(SetOp *from)
 {
-       Limit      *newnode = makeNode(Limit);
+       SetOp      *newnode = makeNode(SetOp);
 
        /*
         * copy node superclass fields
@@ -570,19 +533,21 @@ _copyLimit(Limit *from)
        /*
         * copy remainder of node
         */
-       COPY_NODE_FIELD(limitOffset);
-       COPY_NODE_FIELD(limitCount);
+       COPY_SCALAR_FIELD(cmd);
+       COPY_SCALAR_FIELD(numCols);
+       COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
+       COPY_SCALAR_FIELD(flagColIdx);
 
        return newnode;
 }
 
 /*
- * _copyHash
+ * _copyLimit
  */
-static Hash *
-_copyHash(Hash *from)
+static Limit *
+_copyLimit(Limit *from)
 {
-       Hash       *newnode = makeNode(Hash);
+       Limit      *newnode = makeNode(Limit);
 
        /*
         * copy node superclass fields
@@ -592,9 +557,8 @@ _copyHash(Hash *from)
        /*
         * copy remainder of node
         */
-       COPY_NODE_FIELD(hashkeys);
-
-       /* XXX could the hashkeys contain subplans?  Not at present... */
+       COPY_NODE_FIELD(limitOffset);
+       COPY_NODE_FIELD(limitCount);
 
        return newnode;
 }
@@ -611,10 +575,6 @@ _copySubPlan(SubPlan *from)
        COPY_INTLIST_FIELD(parParam);
        COPY_NODE_FIELD(sublink);
 
-       /* do not copy execution state */
-       newnode->needShutdown = false;
-       newnode->curTuple = NULL;
-
        return newnode;
 }
 
@@ -933,314 +893,12 @@ _copyArrayRef(ArrayRef *from)
 /* ****************************************************************
  *                                             relation.h copy functions
  *
- * XXX the code to copy RelOptInfo and Path nodes is really completely bogus,
- * because it makes no attempt to deal with multiple links from RelOptInfo
- * to Paths, nor with back-links from Paths to their parent RelOptInfo.
- * Currently, since we never actually try to copy a RelOptInfo, this is okay.
+ * We don't support copying RelOptInfo, IndexOptInfo, or Path nodes.
+ * There are some subsidiary structs that are useful to copy, though.
  * ****************************************************************
  */
 
 /*
- * _copyRelOptInfo
- */
-static RelOptInfo *
-_copyRelOptInfo(RelOptInfo *from)
-{
-       RelOptInfo *newnode = makeNode(RelOptInfo);
-
-       COPY_SCALAR_FIELD(reloptkind);
-       COPY_INTLIST_FIELD(relids);
-       COPY_SCALAR_FIELD(rows);
-       COPY_SCALAR_FIELD(width);
-       COPY_NODE_FIELD(targetlist);
-       COPY_NODE_FIELD(pathlist);
-       /* XXX cheapest-path fields should point to members of pathlist? */
-       COPY_NODE_FIELD(cheapest_startup_path);
-       COPY_NODE_FIELD(cheapest_total_path);
-       COPY_SCALAR_FIELD(pruneable);
-       COPY_SCALAR_FIELD(rtekind);
-       COPY_NODE_FIELD(indexlist);
-       COPY_SCALAR_FIELD(pages);
-       COPY_SCALAR_FIELD(tuples);
-       COPY_NODE_FIELD(subplan);
-       COPY_SCALAR_FIELD(joinrti);
-       COPY_INTLIST_FIELD(joinrteids);
-       COPY_NODE_FIELD(baserestrictinfo);
-       COPY_SCALAR_FIELD(baserestrictcost);
-       COPY_INTLIST_FIELD(outerjoinset);
-       COPY_NODE_FIELD(joininfo);
-       COPY_INTLIST_FIELD(index_outer_relids);
-       COPY_NODE_FIELD(index_inner_paths);
-
-       return newnode;
-}
-
-/*
- * _copyIndexOptInfo
- */
-static IndexOptInfo *
-_copyIndexOptInfo(IndexOptInfo *from)
-{
-       IndexOptInfo *newnode = makeNode(IndexOptInfo);
-
-       COPY_SCALAR_FIELD(indexoid);
-       COPY_SCALAR_FIELD(pages);
-       COPY_SCALAR_FIELD(tuples);
-       COPY_SCALAR_FIELD(ncolumns);
-       COPY_SCALAR_FIELD(nkeys);
-
-       if (from->classlist)
-       {
-               /* copy the trailing zero too */
-               COPY_POINTER_FIELD(classlist, (from->ncolumns + 1) * sizeof(Oid));
-       }
-
-       if (from->indexkeys)
-       {
-               /* copy the trailing zero too */
-               COPY_POINTER_FIELD(indexkeys, (from->nkeys + 1) * sizeof(int));
-       }
-
-       if (from->ordering)
-       {
-               /* copy the trailing zero too */
-               COPY_POINTER_FIELD(ordering, (from->ncolumns + 1) * sizeof(Oid));
-       }
-
-       COPY_SCALAR_FIELD(relam);
-       COPY_SCALAR_FIELD(amcostestimate);
-       COPY_SCALAR_FIELD(indproc);
-       COPY_NODE_FIELD(indpred);
-       COPY_SCALAR_FIELD(unique);
-       COPY_INTLIST_FIELD(outer_relids);
-       COPY_NODE_FIELD(inner_paths);
-
-       return newnode;
-}
-
-/*
- * CopyPathFields
- *
- *             This function copies the fields of the Path node.  It is used by
- *             all the copy functions for classes which inherit from Path.
- */
-static void
-CopyPathFields(Path *from, Path *newnode)
-{
-       /*
-        * Modify the next line, since it causes the copying to cycle (i.e.
-        * the parent points right back here! -- JMH, 7/7/92. Old version:
-        * COPY_NODE_FIELD(parent);
-        */
-       COPY_SCALAR_FIELD(parent);
-
-       COPY_SCALAR_FIELD(startup_cost);
-       COPY_SCALAR_FIELD(total_cost);
-       COPY_SCALAR_FIELD(pathtype);
-       COPY_NODE_FIELD(pathkeys);
-}
-
-/*
- * _copyPath
- */
-static Path *
-_copyPath(Path *from)
-{
-       Path       *newnode = makeNode(Path);
-
-       CopyPathFields(from, newnode);
-
-       return newnode;
-}
-
-/*
- * _copyIndexPath
- */
-static IndexPath *
-_copyIndexPath(IndexPath *from)
-{
-       IndexPath  *newnode = makeNode(IndexPath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyPathFields((Path *) from, (Path *) newnode);
-
-       /*
-        * copy remainder of node
-        */
-       COPY_NODE_FIELD(indexinfo);
-       COPY_NODE_FIELD(indexqual);
-       COPY_SCALAR_FIELD(indexscandir);
-       COPY_SCALAR_FIELD(rows);
-
-       return newnode;
-}
-
-/*
- * _copyTidPath
- */
-static TidPath *
-_copyTidPath(TidPath *from)
-{
-       TidPath    *newnode = makeNode(TidPath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyPathFields((Path *) from, (Path *) newnode);
-
-       /*
-        * copy remainder of node
-        */
-       COPY_NODE_FIELD(tideval);
-       COPY_INTLIST_FIELD(unjoined_relids);
-
-       return newnode;
-}
-
-/*
- * _copyAppendPath
- */
-static AppendPath *
-_copyAppendPath(AppendPath *from)
-{
-       AppendPath *newnode = makeNode(AppendPath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyPathFields((Path *) from, (Path *) newnode);
-
-       /*
-        * copy remainder of node
-        */
-       COPY_NODE_FIELD(subpaths);
-
-       return newnode;
-}
-
-/*
- * _copyResultPath
- */
-static ResultPath *
-_copyResultPath(ResultPath *from)
-{
-       ResultPath    *newnode = makeNode(ResultPath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyPathFields((Path *) from, (Path *) newnode);
-
-       /*
-        * copy remainder of node
-        */
-       COPY_NODE_FIELD(subpath);
-       COPY_NODE_FIELD(constantqual);
-
-       return newnode;
-}
-
-/*
- * _copyMaterialPath
- */
-static MaterialPath *
-_copyMaterialPath(MaterialPath *from)
-{
-       MaterialPath    *newnode = makeNode(MaterialPath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyPathFields((Path *) from, (Path *) newnode);
-
-       /*
-        * copy remainder of node
-        */
-       COPY_NODE_FIELD(subpath);
-
-       return newnode;
-}
-
-/*
- * CopyJoinPathFields
- *
- *             This function copies the fields of the JoinPath node.  It is used by
- *             all the copy functions for classes which inherit from JoinPath.
- */
-static void
-CopyJoinPathFields(JoinPath *from, JoinPath *newnode)
-{
-       CopyPathFields((Path *) from, (Path *) newnode);
-
-       COPY_SCALAR_FIELD(jointype);
-       COPY_NODE_FIELD(outerjoinpath);
-       COPY_NODE_FIELD(innerjoinpath);
-       COPY_NODE_FIELD(joinrestrictinfo);
-}
-
-/*
- * _copyNestPath
- */
-static NestPath *
-_copyNestPath(NestPath *from)
-{
-       NestPath   *newnode = makeNode(NestPath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
-
-       return newnode;
-}
-
-/*
- * _copyMergePath
- */
-static MergePath *
-_copyMergePath(MergePath *from)
-{
-       MergePath  *newnode = makeNode(MergePath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
-
-       /*
-        * copy remainder of node
-        */
-       COPY_NODE_FIELD(path_mergeclauses);
-       COPY_NODE_FIELD(outersortkeys);
-       COPY_NODE_FIELD(innersortkeys);
-
-       return newnode;
-}
-
-/*
- * _copyHashPath
- */
-static HashPath *
-_copyHashPath(HashPath *from)
-{
-       HashPath   *newnode = makeNode(HashPath);
-
-       /*
-        * copy node superclass fields
-        */
-       CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
-
-       /*
-        * copy remainder of node
-        */
-       COPY_NODE_FIELD(path_hashclauses);
-
-       return newnode;
-}
-
-/*
  * _copyPathKeyItem
  */
 static PathKeyItem *
@@ -1301,21 +959,6 @@ _copyJoinInfo(JoinInfo *from)
        return newnode;
 }
 
-/*
- * _copyInnerIndexscanInfo
- */
-static InnerIndexscanInfo *
-_copyInnerIndexscanInfo(InnerIndexscanInfo *from)
-{
-       InnerIndexscanInfo   *newnode = makeNode(InnerIndexscanInfo);
-
-       COPY_INTLIST_FIELD(other_relids);
-       COPY_SCALAR_FIELD(isouterjoin);
-       COPY_NODE_FIELD(best_innerpath);
-
-       return newnode;
-}
-
 /* ****************************************************************
  *                                     parsenodes.h copy functions
  * ****************************************************************
@@ -1737,7 +1380,8 @@ _copyQuery(Query *from)
        /*
         * We do not copy the planner internal fields: base_rel_list,
         * other_rel_list, join_rel_list, equi_key_list, query_pathkeys,
-        * hasJoinRTEs.  Not entirely clear if this is right?
+        * hasJoinRTEs.  That would get us into copying RelOptInfo/Path
+        * trees, which we don't want to do.
         */
 
        return newnode;
@@ -2683,15 +2327,15 @@ copyObject(void *from)
                case T_Unique:
                        retval = _copyUnique(from);
                        break;
+               case T_Hash:
+                       retval = _copyHash(from);
+                       break;
                case T_SetOp:
                        retval = _copySetOp(from);
                        break;
                case T_Limit:
                        retval = _copyLimit(from);
                        break;
-               case T_Hash:
-                       retval = _copyHash(from);
-                       break;
                case T_SubPlan:
                        retval = _copySubPlan(from);
                        break;
@@ -2757,39 +2401,6 @@ copyObject(void *from)
                        /*
                         * RELATION NODES
                         */
-               case T_RelOptInfo:
-                       retval = _copyRelOptInfo(from);
-                       break;
-               case T_IndexOptInfo:
-                       retval = _copyIndexOptInfo(from);
-                       break;
-               case T_Path:
-                       retval = _copyPath(from);
-                       break;
-               case T_IndexPath:
-                       retval = _copyIndexPath(from);
-                       break;
-               case T_TidPath:
-                       retval = _copyTidPath(from);
-                       break;
-               case T_AppendPath:
-                       retval = _copyAppendPath(from);
-                       break;
-               case T_ResultPath:
-                       retval = _copyResultPath(from);
-                       break;
-               case T_MaterialPath:
-                       retval = _copyMaterialPath(from);
-                       break;
-               case T_NestPath:
-                       retval = _copyNestPath(from);
-                       break;
-               case T_MergePath:
-                       retval = _copyMergePath(from);
-                       break;
-               case T_HashPath:
-                       retval = _copyHashPath(from);
-                       break;
                case T_PathKeyItem:
                        retval = _copyPathKeyItem(from);
                        break;
@@ -2799,9 +2410,6 @@ copyObject(void *from)
                case T_JoinInfo:
                        retval = _copyJoinInfo(from);
                        break;
-               case T_InnerIndexscanInfo:
-                       retval = _copyInnerIndexscanInfo(from);
-                       break;
 
                        /*
                         * VALUE NODES
index c5a492d..f2cae4c 100644 (file)
@@ -3,30 +3,30 @@
  * equalfuncs.c
  *       Equality functions to compare node trees.
  *
- * NOTE: a general convention when copying or comparing plan nodes is
- * that we ignore the executor state subnode.  We do not need to look
- * at it because no current uses of copyObject() or equal() need to
- * deal with already-executing plan trees.     By leaving the state subnodes
- * out, we avoid needing to write copy/compare routines for all the
- * different executor state node types.
+ * NOTE: we currently support comparing all node types found in parse
+ * trees.  We do not support comparing executor state trees; there
+ * is no need for that, and no point in maintaining all the code that
+ * would be needed.  We also do not support comparing Path trees, mainly
+ * because the circular linkages between RelOptInfo and Path nodes can't
+ * be handled easily in a simple depth-first traversal.
  *
- * Currently, in fact, equal() doesn't know how to compare Plan nodes
- * at all, let alone their executor-state subnodes.  This will probably
- * need to be fixed someday, but presently there is no need to compare
- * plan trees.
+ * Currently, in fact, equal() doesn't know how to compare Plan trees
+ * either.  This might need to be fixed someday.
  *
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.170 2002/11/30 05:21:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.171 2002/12/05 15:50:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
 #include "nodes/plannodes.h"
 #include "nodes/relation.h"
 #include "utils/datum.h"
@@ -370,147 +370,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
  */
 
 static bool
-_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
-{
-       /*
-        * We treat RelOptInfos as equal if they refer to the same base rels
-        * joined in the same order.  Is this appropriate/sufficient?
-        */
-       COMPARE_INTLIST_FIELD(relids);
-
-       return true;
-}
-
-static bool
-_equalIndexOptInfo(IndexOptInfo *a, IndexOptInfo *b)
-{
-       /*
-        * We treat IndexOptInfos as equal if they refer to the same index. Is
-        * this sufficient?
-        */
-       COMPARE_SCALAR_FIELD(indexoid);
-
-       return true;
-}
-
-static bool
-_equalPath(Path *a, Path *b)
-{
-       /* This is safe only because _equalRelOptInfo is incomplete... */
-       COMPARE_NODE_FIELD(parent);
-       /*
-        * do not check path costs, since they may not be set yet, and being
-        * float values there are roundoff error issues anyway...
-        */
-       COMPARE_SCALAR_FIELD(pathtype);
-       COMPARE_NODE_FIELD(pathkeys);
-
-       return true;
-}
-
-static bool
-_equalIndexPath(IndexPath *a, IndexPath *b)
-{
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(indexinfo);
-       COMPARE_NODE_FIELD(indexqual);
-       COMPARE_SCALAR_FIELD(indexscandir);
-
-       /*
-        * Skip 'rows' because of possibility of floating-point roundoff
-        * error. It should be derivable from the other fields anyway.
-        */
-       return true;
-}
-
-static bool
-_equalTidPath(TidPath *a, TidPath *b)
-{
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(tideval);
-       COMPARE_INTLIST_FIELD(unjoined_relids);
-
-       return true;
-}
-
-static bool
-_equalAppendPath(AppendPath *a, AppendPath *b)
-{
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(subpaths);
-
-       return true;
-}
-
-static bool
-_equalResultPath(ResultPath *a, ResultPath *b)
-{
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(subpath);
-       COMPARE_NODE_FIELD(constantqual);
-
-       return true;
-}
-
-static bool
-_equalMaterialPath(MaterialPath *a, MaterialPath *b)
-{
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(subpath);
-
-       return true;
-}
-
-static bool
-_equalJoinPath(JoinPath *a, JoinPath *b)
-{
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_SCALAR_FIELD(jointype);
-       COMPARE_NODE_FIELD(outerjoinpath);
-       COMPARE_NODE_FIELD(innerjoinpath);
-       COMPARE_NODE_FIELD(joinrestrictinfo);
-
-       return true;
-}
-
-static bool
-_equalNestPath(NestPath *a, NestPath *b)
-{
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
-
-       return true;
-}
-
-static bool
-_equalMergePath(MergePath *a, MergePath *b)
-{
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
-       COMPARE_NODE_FIELD(path_mergeclauses);
-       COMPARE_NODE_FIELD(outersortkeys);
-       COMPARE_NODE_FIELD(innersortkeys);
-
-       return true;
-}
-
-static bool
-_equalHashPath(HashPath *a, HashPath *b)
-{
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
-       COMPARE_NODE_FIELD(path_hashclauses);
-
-       return true;
-}
-
-static bool
 _equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
 {
        COMPARE_NODE_FIELD(key);
@@ -547,16 +406,6 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b)
        return true;
 }
 
-static bool
-_equalInnerIndexscanInfo(InnerIndexscanInfo *a, InnerIndexscanInfo *b)
-{
-       COMPARE_INTLIST_FIELD(other_relids);
-       COMPARE_SCALAR_FIELD(isouterjoin);
-       COMPARE_NODE_FIELD(best_innerpath);
-
-       return true;
-}
-
 
 /*
  * Stuff from parsenodes.h
@@ -1711,39 +1560,6 @@ equal(void *a, void *b)
                        retval = _equalJoinExpr(a, b);
                        break;
 
-               case T_RelOptInfo:
-                       retval = _equalRelOptInfo(a, b);
-                       break;
-               case T_IndexOptInfo:
-                       retval = _equalIndexOptInfo(a, b);
-                       break;
-               case T_Path:
-                       retval = _equalPath(a, b);
-                       break;
-               case T_IndexPath:
-                       retval = _equalIndexPath(a, b);
-                       break;
-               case T_TidPath:
-                       retval = _equalTidPath(a, b);
-                       break;
-               case T_AppendPath:
-                       retval = _equalAppendPath(a, b);
-                       break;
-               case T_ResultPath:
-                       retval = _equalResultPath(a, b);
-                       break;
-               case T_MaterialPath:
-                       retval = _equalMaterialPath(a, b);
-                       break;
-               case T_NestPath:
-                       retval = _equalNestPath(a, b);
-                       break;
-               case T_MergePath:
-                       retval = _equalMergePath(a, b);
-                       break;
-               case T_HashPath:
-                       retval = _equalHashPath(a, b);
-                       break;
                case T_PathKeyItem:
                        retval = _equalPathKeyItem(a, b);
                        break;
@@ -1753,9 +1569,6 @@ equal(void *a, void *b)
                case T_JoinInfo:
                        retval = _equalJoinInfo(a, b);
                        break;
-               case T_InnerIndexscanInfo:
-                       retval = _equalInnerIndexscanInfo(a, b);
-                       break;
 
                case T_List:
                        {
index 3a07433..2c25400 100644 (file)
@@ -8,13 +8,13 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.185 2002/11/30 05:21:02 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.186 2002/12/05 15:50:35 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
  *       have an output function defined here (as well as an input function
  *       in readfuncs.c).  For use in debugging, we also provide output
- *       functions for nodes that appear in raw parsetrees and plan trees.
+ *       functions for nodes that appear in raw parsetrees, path, and plan trees.
  *       These nodes however need not have input functions.
  *
  *-------------------------------------------------------------------------
 #include <ctype.h>
 
 #include "lib/stringinfo.h"
-#include "nodes/nodes.h"
 #include "nodes/parsenodes.h"
 #include "nodes/plannodes.h"
-#include "nodes/primnodes.h"
 #include "nodes/relation.h"
 #include "parser/parse.h"
 #include "utils/datum.h"
@@ -385,11 +383,9 @@ _outPlanInfo(StringInfo str, Plan *node)
        WRITE_NODE_FIELD(qual);
        WRITE_NODE_FIELD(lefttree);
        WRITE_NODE_FIELD(righttree);
+       WRITE_NODE_FIELD(initPlan);
        WRITE_INTLIST_FIELD(extParam);
        WRITE_INTLIST_FIELD(locParam);
-       /* chgParam is execution state too */
-       WRITE_NODE_FIELD(initPlan);
-       /* we don't write subPlan; reader must reconstruct list */
        WRITE_INT_FIELD(nParamExec);
 }
 
@@ -482,7 +478,6 @@ _outTidScan(StringInfo str, TidScan *node)
 
        _outScanInfo(str, (Scan *) node);
 
-       WRITE_BOOL_FIELD(needRescan);
        WRITE_NODE_FIELD(tideval);
 }
 
@@ -930,6 +925,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
 
 /*
  * print the basic stuff of all nodes that inherit from Path
+ *
+ * Note we do NOT print the parent, else we'd be in infinite recursion
  */
 static void
 _outPathInfo(StringInfo str, Path *node)
@@ -986,7 +983,6 @@ _outTidPath(StringInfo str, TidPath *node)
        _outPathInfo(str, (Path *) node);
 
        WRITE_NODE_FIELD(tideval);
-       WRITE_INTLIST_FIELD(unjoined_relids);
 }
 
 static void
index 148bd86..0414fdf 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.126 2002/11/30 05:21:02 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.127 2002/12/05 15:50:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -602,9 +602,6 @@ create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses)
                                                         scan_relid,
                                                         best_path->tideval);
 
-       if (best_path->unjoined_relids)
-               scan_plan->needRescan = true;
-
        copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
 
        return scan_plan;
@@ -1302,13 +1299,11 @@ make_seqscan(List *qptlist,
        Plan       *plan = &node->plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = qptlist;
        plan->qual = qpqual;
        plan->lefttree = NULL;
        plan->righttree = NULL;
        node->scanrelid = scanrelid;
-       node->scanstate = (CommonScanState *) NULL;
 
        return node;
 }
@@ -1326,7 +1321,6 @@ make_indexscan(List *qptlist,
        Plan       *plan = &node->scan.plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = qptlist;
        plan->qual = qpqual;
        plan->lefttree = NULL;
@@ -1336,7 +1330,6 @@ make_indexscan(List *qptlist,
        node->indxqual = indxqual;
        node->indxqualorig = indxqualorig;
        node->indxorderdir = indexscandir;
-       node->scan.scanstate = (CommonScanState *) NULL;
 
        return node;
 }
@@ -1351,16 +1344,12 @@ make_tidscan(List *qptlist,
        Plan       *plan = &node->scan.plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = qptlist;
        plan->qual = qpqual;
        plan->lefttree = NULL;
        plan->righttree = NULL;
        node->scan.scanrelid = scanrelid;
-       node->tideval = copyObject(tideval);            /* XXX do we really need a
-                                                                                                * copy? */
-       node->needRescan = false;
-       node->scan.scanstate = (CommonScanState *) NULL;
+       node->tideval = tideval;
 
        return node;
 }
@@ -1375,14 +1364,12 @@ make_subqueryscan(List *qptlist,
        Plan       *plan = &node->scan.plan;
 
        copy_plan_costsize(plan, subplan);
-       plan->state = (EState *) NULL;
        plan->targetlist = qptlist;
        plan->qual = qpqual;
        plan->lefttree = NULL;
        plan->righttree = NULL;
        node->scan.scanrelid = scanrelid;
        node->subplan = subplan;
-       node->scan.scanstate = (CommonScanState *) NULL;
 
        return node;
 }
@@ -1396,13 +1383,11 @@ make_functionscan(List *qptlist,
        Plan       *plan = &node->scan.plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = qptlist;
        plan->qual = qpqual;
        plan->lefttree = NULL;
        plan->righttree = NULL;
        node->scan.scanrelid = scanrelid;
-       node->scan.scanstate = (CommonScanState *) NULL;
 
        return node;
 }
@@ -1430,7 +1415,6 @@ make_append(List *appendplans, bool isTarget, List *tlist)
                if (plan->plan_width < subplan->plan_width)
                        plan->plan_width = subplan->plan_width;
        }
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NIL;
        plan->lefttree = NULL;
@@ -1453,7 +1437,6 @@ make_nestloop(List *tlist,
        Plan       *plan = &node->join.plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = otherclauses;
        plan->lefttree = lefttree;
@@ -1477,7 +1460,6 @@ make_hashjoin(List *tlist,
        Plan       *plan = &node->join.plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = otherclauses;
        plan->lefttree = lefttree;
@@ -1502,7 +1484,6 @@ make_hash(List *tlist, List *hashkeys, Plan *lefttree)
         * input plan; this only affects EXPLAIN display not decisions.
         */
        plan->startup_cost = plan->total_cost;
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NULL;
        plan->lefttree = lefttree;
@@ -1525,7 +1506,6 @@ make_mergejoin(List *tlist,
        Plan       *plan = &node->join.plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = otherclauses;
        plan->lefttree = lefttree;
@@ -1557,7 +1537,6 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int keycount)
                          lefttree->plan_width);
        plan->startup_cost = sort_path.startup_cost;
        plan->total_cost = sort_path.total_cost;
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NIL;
        plan->lefttree = lefttree;
@@ -1646,7 +1625,6 @@ make_material(List *tlist, Plan *lefttree)
        Plan       *plan = &node->plan;
 
        /* cost should be inserted by caller */
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NIL;
        plan->lefttree = lefttree;
@@ -1690,7 +1668,6 @@ make_agg(Query *root, List *tlist, List *qual,
        else
                plan->plan_rows = numGroups;
 
-       plan->state = (EState *) NULL;
        plan->qual = qual;
        plan->targetlist = tlist;
        plan->lefttree = lefttree;
@@ -1726,7 +1703,6 @@ make_group(Query *root,
        /* One output tuple per estimated result group */
        plan->plan_rows = numGroups;
 
-       plan->state = (EState *) NULL;
        plan->qual = NULL;
        plan->targetlist = tlist;
        plan->lefttree = lefttree;
@@ -1765,7 +1741,6 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList)
         * if he has a better idea.
         */
 
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NIL;
        plan->lefttree = lefttree;
@@ -1824,7 +1799,6 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
        if (plan->plan_rows < 1)
                plan->plan_rows = 1;
 
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NIL;
        plan->lefttree = lefttree;
@@ -1905,7 +1879,6 @@ make_limit(List *tlist, Plan *lefttree,
                }
        }
 
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NIL;
        plan->lefttree = lefttree;
@@ -1935,13 +1908,11 @@ make_result(List *tlist,
                plan->plan_width = 0;   /* XXX try to be smarter? */
        }
 
-       plan->state = (EState *) NULL;
        plan->targetlist = tlist;
        plan->qual = NIL;
        plan->lefttree = subplan;
        plan->righttree = NULL;
        node->resconstantqual = resconstantqual;
-       node->resstate = NULL;
 
        return node;
 }
index 3db73e8..b23843a 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.83 2002/11/30 21:25:04 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.84 2002/12/05 15:50:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,6 +41,7 @@ typedef struct
 } replace_vars_with_subplan_refs_context;
 
 static void fix_expr_references(Plan *plan, Node *node);
+static bool fix_expr_references_walker(Node *node, void *context);
 static void set_join_references(Join *join, List *rtable);
 static void set_uppernode_references(Plan *plan, Index subvarno);
 static Node *join_references_mutator(Node *node,
@@ -66,8 +67,6 @@ static bool fix_opids_walker(Node *node, void *context);
  *       for the convenience of the executor.  We update Vars in upper plan nodes
  *       to refer to the outputs of their subplans, and we compute regproc OIDs
  *       for operators (ie, we look up the function that implements each op).
- *       We must also build lists of all the subplan nodes present in each
- *       plan node's expression trees.
  *
  *       set_plan_references recursively traverses the whole plan tree.
  *
@@ -82,12 +81,6 @@ set_plan_references(Plan *plan, List *rtable)
                return;
 
        /*
-        * We must rebuild the plan's list of subplan nodes, since we are
-        * copying/mutating its expression trees.
-        */
-       plan->subPlan = NIL;
-
-       /*
         * Plan-type-specific fixes
         */
        switch (nodeTag(plan))
@@ -107,6 +100,8 @@ set_plan_references(Plan *plan, List *rtable)
                case T_TidScan:
                        fix_expr_references(plan, (Node *) plan->targetlist);
                        fix_expr_references(plan, (Node *) plan->qual);
+                       fix_expr_references(plan,
+                                                               (Node *) ((TidScan *) plan)->tideval);
                        break;
                case T_SubqueryScan:
                        {
@@ -175,9 +170,9 @@ set_plan_references(Plan *plan, List *rtable)
                         * unmodified input tuples).  The optimizer is lazy about
                         * creating really valid targetlists for them.  Best to just
                         * leave the targetlist alone.  In particular, we do not want
-                        * to pull a subplan list for them, since we will likely end
-                        * up with duplicate list entries for subplans that also
-                        * appear in lower levels of the plan tree!
+                        * to process subplans for them, since we will likely end
+                        * up reprocessing subplans that also appear in lower levels
+                        * of the plan tree!
                         */
                        break;
                case T_Agg:
@@ -206,7 +201,7 @@ set_plan_references(Plan *plan, List *rtable)
                         * Append, like Sort et al, doesn't actually evaluate its
                         * targetlist or quals, and we haven't bothered to give it its
                         * own tlist copy.      So, don't fix targetlist/qual. But do
-                        * recurse into subplans.
+                        * recurse into child plans.
                         */
                        foreach(pl, ((Append *) plan)->appendplans)
                                set_plan_references((Plan *) lfirst(pl), rtable);
@@ -218,24 +213,19 @@ set_plan_references(Plan *plan, List *rtable)
        }
 
        /*
-        * Now recurse into subplans, if any
+        * Now recurse into child plans and initplans, if any
         *
-        * NOTE: it is essential that we recurse into subplans AFTER we set
+        * NOTE: it is essential that we recurse into child plans AFTER we set
         * subplan references in this plan's tlist and quals.  If we did the
         * reference-adjustments bottom-up, then we would fail to match this
         * plan's var nodes against the already-modified nodes of the
-        * subplans.
+        * children.  Fortunately, that consideration doesn't apply to SubPlan
+        * nodes; else we'd need two passes over the expression trees.
         */
        set_plan_references(plan->lefttree, rtable);
        set_plan_references(plan->righttree, rtable);
-       foreach(pl, plan->initPlan)
-       {
-               SubPlan    *sp = (SubPlan *) lfirst(pl);
 
-               Assert(IsA(sp, SubPlan));
-               set_plan_references(sp->plan, sp->rtable);
-       }
-       foreach(pl, plan->subPlan)
+       foreach(pl, plan->initPlan)
        {
                SubPlan    *sp = (SubPlan *) lfirst(pl);
 
@@ -249,13 +239,38 @@ set_plan_references(Plan *plan, List *rtable)
  *       Do final cleanup on expressions (targetlists or quals).
  *
  * This consists of looking up operator opcode info for Oper nodes
- * and adding subplans to the Plan node's list of contained subplans.
+ * and recursively performing set_plan_references on SubPlans.
+ *
+ * The Plan argument is currently unused, but might be needed again someday.
  */
 static void
 fix_expr_references(Plan *plan, Node *node)
 {
-       fix_opids(node);
-       plan->subPlan = nconc(plan->subPlan, pull_subplans(node));
+       /* This tree walk requires no special setup, so away we go... */
+       fix_expr_references_walker(node, NULL);
+}
+
+static bool
+fix_expr_references_walker(Node *node, void *context)
+{
+       if (node == NULL)
+               return false;
+       if (IsA(node, Expr))
+       {
+               Expr   *expr = (Expr *) node;
+
+               if (expr->opType == OP_EXPR ||
+                       expr->opType == DISTINCT_EXPR)
+                       replace_opid((Oper *) expr->oper);
+               else if (expr->opType == SUBPLAN_EXPR)
+               {
+                       SubPlan    *sp = (SubPlan *) expr->oper;
+
+                       Assert(IsA(sp, SubPlan));
+                       set_plan_references(sp->plan, sp->rtable);
+               }
+       }
+       return expression_tree_walker(node, fix_expr_references_walker, context);
 }
 
 /*
index e4bbd29..a65de72 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.58 2002/11/30 05:21:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.59 2002/12/05 15:50:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 #include "catalog/pg_operator.h"
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
+#include "nodes/params.h"
 #include "optimizer/clauses.h"
 #include "optimizer/cost.h"
 #include "optimizer/planmain.h"
@@ -297,7 +298,7 @@ make_subplan(SubLink *slink)
                        switch (nodeTag(plan))
                        {
                                case T_SeqScan:
-                                       if (plan->initPlan || plan->subPlan)
+                                       if (plan->initPlan)
                                                use_material = true;
                                        else
                                        {
@@ -453,20 +454,13 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
 }
 
 /*
- * finalize_primnode: build lists of subplans and params appearing
- * in the given expression tree.  NOTE: items are added to lists passed in,
- * so caller must initialize lists to NIL before first call!
- *
- * Note: the subplan list that is constructed here and assigned to the
- * plan's subPlan field will be replaced with an up-to-date list in
- * set_plan_references().  We could almost dispense with building this
- * subplan list at all; I believe the only place that uses it is the
- * check in make_subplan to see whether a subselect has any subselects.
+ * finalize_primnode: build lists of params appearing
+ * in the given expression tree.  NOTE: items are added to list passed in,
+ * so caller must initialize list to NIL before first call!
  */
 
 typedef struct finalize_primnode_results
 {
-       List       *subplans;           /* List of subplans found in expr */
        List       *paramids;           /* List of PARAM_EXEC paramids found */
 } finalize_primnode_results;
 
@@ -491,8 +485,6 @@ finalize_primnode(Node *node, finalize_primnode_results *results)
                SubPlan    *subplan = (SubPlan *) ((Expr *) node)->oper;
                List       *lst;
 
-               /* Add subplan to subplans list */
-               results->subplans = lappend(results->subplans, subplan);
                /* Check extParam list for params to add to paramids */
                foreach(lst, subplan->plan->extParam)
                {
@@ -595,18 +587,16 @@ SS_finalize_plan(Plan *plan, List *rtable)
        if (plan == NULL)
                return NIL;
 
-       results.subplans = NIL;         /* initialize lists to NIL */
-       results.paramids = NIL;
+       results.paramids = NIL;         /* initialize list to NIL */
 
        /*
         * When we call finalize_primnode, results.paramids lists are
         * automatically merged together.  But when recursing to self, we have
         * to do it the hard way.  We want the paramids list to include params
-        * in subplans as well as at this level. (We don't care about finding
-        * subplans of subplans, though.)
+        * in subplans as well as at this level.
         */
 
-       /* Find params and subplans in targetlist and qual */
+       /* Find params in targetlist and qual */
        finalize_primnode((Node *) plan->targetlist, &results);
        finalize_primnode((Node *) plan->qual, &results);
 
@@ -624,8 +614,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
 
                        /*
                         * we need not look at indxqualorig, since it will have the
-                        * same param references as indxqual, and we aren't really
-                        * concerned yet about having a complete subplan list.
+                        * same param references as indxqual.
                         */
                        break;
 
@@ -704,7 +693,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
                                 nodeTag(plan));
        }
 
-       /* Process left and right subplans, if any */
+       /* Process left and right child plans, if any */
        results.paramids = set_unioni(results.paramids,
                                                                  SS_finalize_plan(plan->lefttree,
                                                                                                   rtable));
@@ -712,7 +701,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
                                                                  SS_finalize_plan(plan->righttree,
                                                                                                   rtable));
 
-       /* Now we have all the paramids and subplans */
+       /* Now we have all the paramids */
 
        foreach(lst, results.paramids)
        {
@@ -733,7 +722,6 @@ SS_finalize_plan(Plan *plan, List *rtable)
 
        plan->extParam = extParam;
        plan->locParam = locParam;
-       plan->subPlan = results.subplans;
 
        return results.paramids;
 }
index 84896b9..615d996 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.82 2002/11/30 05:21:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.83 2002/12/05 15:50:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -385,9 +385,7 @@ create_tidscan_path(Query *root, RelOptInfo *rel, List *tideval)
        pathnode->path.pathtype = T_TidScan;
        pathnode->path.parent = rel;
        pathnode->path.pathkeys = NIL;
-       pathnode->tideval = copyObject(tideval);        /* is copy really
-                                                                                                * necessary? */
-       pathnode->unjoined_relids = NIL;
+       pathnode->tideval = tideval;
 
        cost_tidscan(&pathnode->path, root, rel, tideval);
 
index 0919b03..24d4aac 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.56 2002/11/18 01:17:39 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.57 2002/12/05 15:50:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/ps_status.h"
 
 
-/* ----------------------------------------------------------------
- *             CreateQueryDesc
- * ----------------------------------------------------------------
+/*
+ * CreateQueryDesc
  */
 QueryDesc *
 CreateQueryDesc(Query *parsetree,
                                Plan *plantree,
                                CommandDest dest,
-                               const char *portalName)
+                               const char *portalName,
+                               ParamListInfo params,
+                               bool doInstrument)
 {
        QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
 
@@ -40,54 +41,15 @@ CreateQueryDesc(Query *parsetree,
        qd->plantree = plantree;        /* plan */
        qd->dest = dest;                        /* output dest */
        qd->portalName = portalName;    /* name, if dest is a portal */
-       qd->tupDesc = NULL;                     /* until set by ExecutorStart */
-
-       return qd;
-}
-
-/* ----------------------------------------------------------------
- *             CreateExecutorState
- *
- *             Note: this may someday take parameters -cim 9/18/89
- * ----------------------------------------------------------------
- */
-EState *
-CreateExecutorState(void)
-{
-       EState     *state;
-
-       /*
-        * create a new executor state
-        */
-       state = makeNode(EState);
-
-       /*
-        * initialize the Executor State structure
-        */
-       state->es_direction = ForwardScanDirection;
-       state->es_range_table = NIL;
-
-       state->es_result_relations = NULL;
-       state->es_num_result_relations = 0;
-       state->es_result_relation_info = NULL;
-
-       state->es_junkFilter = NULL;
-
-       state->es_into_relation_descriptor = NULL;
-
-       state->es_param_list_info = NULL;
-       state->es_param_exec_vals = NULL;
-
-       state->es_tupleTable = NULL;
-
-       state->es_query_cxt = CurrentMemoryContext;
+       qd->params = params;            /* parameter values passed into query */
+       qd->doInstrument = doInstrument; /* instrumentation wanted? */
 
-       state->es_per_tuple_exprcontext = NULL;
+       /* null these fields until set by ExecutorStart */
+       qd->tupDesc = NULL;
+       qd->estate = NULL;
+       qd->planstate = NULL;
 
-       /*
-        * return the executor state structure
-        */
-       return state;
+       return qd;
 }
 
 /* ----------------
@@ -147,8 +109,6 @@ ProcessQuery(Query *parsetree,
        Portal          portal = NULL;
        MemoryContext oldContext = NULL;
        QueryDesc  *queryDesc;
-       EState     *state;
-       TupleDesc       attinfo;
 
        /*
         * Check for special-case destinations
@@ -193,7 +153,7 @@ ProcessQuery(Query *parsetree,
 
                /*
                 * We stay in portal's memory context for now, so that query desc,
-                * EState, and plan startup info are also allocated in the portal
+                * exec state, and plan startup info are also allocated in the portal
                 * context.
                 */
        }
@@ -201,17 +161,12 @@ ProcessQuery(Query *parsetree,
        /*
         * Now we can create the QueryDesc object.
         */
-       queryDesc = CreateQueryDesc(parsetree, plan, dest, intoName);
-
-       /*
-        * create a default executor state.
-        */
-       state = CreateExecutorState();
+       queryDesc = CreateQueryDesc(parsetree, plan, dest, intoName, NULL, false);
 
        /*
         * call ExecStart to prepare the plan for execution
         */
-       attinfo = ExecutorStart(queryDesc, state);
+       ExecutorStart(queryDesc);
 
        /*
         * If retrieve into portal, stop now; we do not run the plan until a
@@ -219,11 +174,8 @@ ProcessQuery(Query *parsetree,
         */
        if (isRetrieveIntoPortal)
        {
-               PortalSetQuery(portal,
-                                          queryDesc,
-                                          attinfo,
-                                          state,
-                                          PortalCleanup);
+               /* Arrange to shut down the executor if portal is dropped */
+               PortalSetQuery(portal, queryDesc, PortalCleanup);
 
                /* Now we can return to caller's memory context. */
                MemoryContextSwitchTo(oldContext);
@@ -239,7 +191,7 @@ ProcessQuery(Query *parsetree,
         * Now we get to the important call to ExecutorRun() where we actually
         * run the plan..
         */
-       ExecutorRun(queryDesc, state, ForwardScanDirection, 0L);
+       ExecutorRun(queryDesc, ForwardScanDirection, 0L);
 
        /*
         * Build command completion status string, if caller wants one.
@@ -254,20 +206,20 @@ ProcessQuery(Query *parsetree,
                                strcpy(completionTag, "SELECT");
                                break;
                        case CMD_INSERT:
-                               if (state->es_processed == 1)
-                                       lastOid = state->es_lastoid;
+                               if (queryDesc->estate->es_processed == 1)
+                                       lastOid = queryDesc->estate->es_lastoid;
                                else
                                        lastOid = InvalidOid;
                                snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
-                                                "INSERT %u %u", lastOid, state->es_processed);
+                                                "INSERT %u %u", lastOid, queryDesc->estate->es_processed);
                                break;
                        case CMD_UPDATE:
                                snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
-                                                "UPDATE %u", state->es_processed);
+                                                "UPDATE %u", queryDesc->estate->es_processed);
                                break;
                        case CMD_DELETE:
                                snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
-                                                "DELETE %u", state->es_processed);
+                                                "DELETE %u", queryDesc->estate->es_processed);
                                break;
                        default:
                                strcpy(completionTag, "???");
@@ -278,5 +230,5 @@ ProcessQuery(Query *parsetree,
        /*
         * Now, we close down all the scans and free allocated resources.
         */
-       ExecutorEnd(queryDesc, state);
+       ExecutorEnd(queryDesc);
 }
index 4805c44..eaead7d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.49 2002/06/20 20:29:40 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.50 2002/12/05 15:50:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -149,26 +149,15 @@ GetPortalByName(char *name)
 /*
  * PortalSetQuery
  *             Attaches a "query" to portal.
- *
- * Exceptions:
- *             BadState if called when disabled.
- *             BadArg if portal is invalid.
- *             BadArg if queryDesc is "invalid."
- *             BadArg if state is "invalid."
  */
 void
 PortalSetQuery(Portal portal,
                           QueryDesc *queryDesc,
-                          TupleDesc attinfo,
-                          EState *state,
                           void (*cleanup) (Portal portal))
 {
        AssertArg(PortalIsValid(portal));
-       AssertArg(IsA((Node *) state, EState));
 
        portal->queryDesc = queryDesc;
-       portal->attinfo = attinfo;
-       portal->state = state;
        portal->atStart = true;         /* Allow fetch forward only */
        portal->atEnd = false;
        portal->cleanup = cleanup;
@@ -212,8 +201,6 @@ CreatePortal(char *name)
 
        /* initialize portal query */
        portal->queryDesc = NULL;
-       portal->attinfo = NULL;
-       portal->state = NULL;
        portal->atStart = true;         /* disallow fetches until query is set */
        portal->atEnd = true;
        portal->cleanup = NULL;
index 363dabe..9a95551 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: execdesc.h,v 1.20 2002/09/04 20:31:42 momjian Exp $
+ * $Id: execdesc.h,v 1.21 2002/12/05 15:50:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define EXECDESC_H
 
 #include "nodes/parsenodes.h"
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 #include "tcop/dest.h"
 
 
 /* ----------------
  *             query descriptor:
+ *
  *     a QueryDesc encapsulates everything that the executor
  *     needs to execute the query
  * ---------------------
  */
 typedef struct QueryDesc
 {
+       /* These fields are provided by CreateQueryDesc */
        CmdType         operation;              /* CMD_SELECT, CMD_UPDATE, etc. */
-       Query      *parsetree;
-       Plan       *plantree;
+       Query      *parsetree;          /* rewritten parsetree */
+       Plan       *plantree;           /* planner's output */
        CommandDest dest;                       /* the destination output of the execution */
        const char *portalName;         /* name of portal, or NULL */
+       ParamListInfo params;           /* param values being passed in */
+       bool            doInstrument;   /* TRUE requests runtime instrumentation */
 
-       TupleDesc       tupDesc;                /* set by ExecutorStart */
+       /* These fields are set by ExecutorStart */
+       TupleDesc       tupDesc;                /* descriptor for result tuples */
+       EState     *estate;                     /* executor's query-wide state */
+       PlanState  *planstate;          /* tree of per-plan-node state */
 } QueryDesc;
 
 /* in pquery.c */
 extern QueryDesc *CreateQueryDesc(Query *parsetree, Plan *plantree,
-                               CommandDest dest, const char *portalName);
-
+                                                                 CommandDest dest, const char *portalName,
+                                                                 ParamListInfo params,
+                                                                 bool doInstrument);
 
 #endif   /* EXECDESC_H  */
index 33b83bc..df3e52d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: executor.h,v 1.80 2002/12/01 20:27:32 tgl Exp $
+ * $Id: executor.h,v 1.81 2002/12/05 15:50:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "executor/execdesc.h"
 
+
 /* ----------------
  *             TupIsNull
  *
@@ -30,9 +31,9 @@
 /*
  * prototypes from functions in execAmi.c
  */
-extern void ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent);
-extern void ExecMarkPos(Plan *node);
-extern void ExecRestrPos(Plan *node);
+extern void ExecReScan(PlanState *node, ExprContext *exprCtxt);
+extern void ExecMarkPos(PlanState *node);
+extern void ExecRestrPos(PlanState *node);
 extern bool ExecSupportsMarkRestore(NodeTag plantype);
 
 /*
@@ -49,10 +50,12 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
 /*
  * prototypes from functions in execMain.c
  */
-extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate);
-extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate,
+extern void ExecutorStart(QueryDesc *queryDesc);
+extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
                        ScanDirection direction, long count);
-extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
+extern void ExecutorEnd(QueryDesc *queryDesc);
+extern EState *CreateExecutorState(void);
+extern void ExecCheckRTPerms(List *rangeTable, CmdType operation);
 extern void ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo,
                                TupleTableSlot *slot, EState *estate);
 extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
@@ -61,11 +64,11 @@ extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
 /*
  * prototypes from functions in execProcnode.c
  */
-extern bool ExecInitNode(Plan *node, EState *estate, Plan *parent);
-extern TupleTableSlot *ExecProcNode(Plan *node, Plan *parent);
+extern PlanState *ExecInitNode(Plan *node, EState *estate);
+extern TupleTableSlot *ExecProcNode(PlanState *node);
 extern int     ExecCountSlotsNode(Plan *node);
-extern void ExecEndNode(Plan *node, Plan *parent);
-extern TupleDesc ExecGetTupType(Plan *node);
+extern void ExecEndNode(PlanState *node);
+extern TupleDesc ExecGetTupType(PlanState *node);
 
 /*
  * prototypes from functions in execQual.c
@@ -89,6 +92,7 @@ extern Datum ExecEvalExpr(Node *expression, ExprContext *econtext,
                         bool *isNull, ExprDoneCond *isDone);
 extern Datum ExecEvalExprSwitchContext(Node *expression, ExprContext *econtext,
                                                  bool *isNull, ExprDoneCond *isDone);
+extern Node *ExecInitExpr(Node *node, PlanState *parent);
 extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
 extern int     ExecTargetListLength(List *targetlist);
 extern int     ExecCleanTargetListLength(List *targetlist);
@@ -98,9 +102,9 @@ extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo,
 /*
  * prototypes from functions in execScan.c
  */
-typedef TupleTableSlot *(*ExecScanAccessMtd) (Scan *node);
+typedef TupleTableSlot *(*ExecScanAccessMtd) (ScanState *node);
 
-extern TupleTableSlot *ExecScan(Scan *node, ExecScanAccessMtd accessMtd);
+extern TupleTableSlot *ExecScan(ScanState *node, ExecScanAccessMtd accessMtd);
 
 /*
  * prototypes from functions in execTuples.c
@@ -117,14 +121,13 @@ extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
 extern void ExecSetSlotDescriptor(TupleTableSlot *slot,
                                          TupleDesc tupdesc, bool shouldFree);
 extern void ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, bool isNew);
-extern void ExecInitResultTupleSlot(EState *estate, CommonState *commonstate);
-extern void ExecInitScanTupleSlot(EState *estate,
-                                         CommonScanState *commonscanstate);
+extern void ExecInitResultTupleSlot(EState *estate, PlanState *planstate);
+extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate);
 extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
 extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
                                          TupleDesc tupType);
 extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
-extern void SetChangedParamList(Plan *node, List *newchg);
+extern void SetChangedParamList(PlanState *node, List *newchg);
 
 typedef struct TupOutputState
 {
@@ -155,21 +158,19 @@ extern void end_tup_output(TupOutputState *tstate);
  * prototypes from functions in execUtils.c
  */
 extern void ResetTupleCount(void);
-extern void ExecAssignExprContext(EState *estate, CommonState *commonstate);
-extern void ExecAssignResultType(CommonState *commonstate,
+extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
+extern void ExecAssignResultType(PlanState *planstate,
                                         TupleDesc tupDesc, bool shouldFree);
-extern void ExecAssignResultTypeFromOuterPlan(Plan *node,
-                                                                 CommonState *commonstate);
-extern void ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate);
-extern TupleDesc ExecGetResultType(CommonState *commonstate);
-extern void ExecAssignProjectionInfo(Plan *node, CommonState *commonstate);
-extern void ExecFreeProjectionInfo(CommonState *commonstate);
-extern void ExecFreeExprContext(CommonState *commonstate);
-extern TupleDesc ExecGetScanType(CommonScanState *csstate);
-extern void ExecAssignScanType(CommonScanState *csstate,
+extern void ExecAssignResultTypeFromOuterPlan(PlanState *planstate);
+extern void ExecAssignResultTypeFromTL(PlanState *planstate);
+extern TupleDesc ExecGetResultType(PlanState *planstate);
+extern void ExecAssignProjectionInfo(PlanState *planstate);
+extern void ExecFreeProjectionInfo(PlanState *planstate);
+extern void ExecFreeExprContext(PlanState *planstate);
+extern TupleDesc ExecGetScanType(ScanState *scanstate);
+extern void ExecAssignScanType(ScanState *scanstate,
                                   TupleDesc tupDesc, bool shouldFree);
-extern void ExecAssignScanTypeFromOuterPlan(Plan *node,
-                                                               CommonScanState *csstate);
+extern void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate);
 
 extern ExprContext *MakeExprContext(TupleTableSlot *slot,
                                MemoryContext queryContext);
index c912d3c..036d67c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeAgg.h,v 1.17 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeAgg.h,v 1.18 2002/12/05 15:50:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define NODEAGG_H
 
 #include "fmgr.h"
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecAgg(Agg *node);
-extern bool ExecInitAgg(Agg *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsAgg(Agg *node);
-extern void ExecEndAgg(Agg *node);
-extern void ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent);
+extern AggState *ExecInitAgg(Agg *node, EState *estate);
+extern TupleTableSlot *ExecAgg(AggState *node);
+extern void ExecEndAgg(AggState *node);
+extern void ExecReScanAgg(AggState *node, ExprContext *exprCtxt);
 
 extern Datum aggregate_dummy(PG_FUNCTION_ARGS);
 
index 4e9255b..3d18b66 100644 (file)
@@ -7,19 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeAppend.h,v 1.17 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeAppend.h,v 1.18 2002/12/05 15:50:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEAPPEND_H
 #define NODEAPPEND_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern bool ExecInitAppend(Append *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsAppend(Append *node);
-extern TupleTableSlot *ExecProcAppend(Append *node);
-extern void ExecEndAppend(Append *node);
-extern void ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent);
+extern AppendState *ExecInitAppend(Append *node, EState *estate);
+extern TupleTableSlot *ExecProcAppend(AppendState *node);
+extern void ExecEndAppend(AppendState *node);
+extern void ExecReScanAppend(AppendState *node, ExprContext *exprCtxt);
 
 #endif   /* NODEAPPEND_H */
index 9a59cd2..893d6b0 100644 (file)
@@ -7,21 +7,21 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeFunctionscan.h,v 1.2 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeFunctionscan.h,v 1.3 2002/12/05 15:50:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEFUNCTIONSCAN_H
 #define NODEFUNCTIONSCAN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecFunctionScan(FunctionScan *node);
-extern void ExecEndFunctionScan(FunctionScan *node);
-extern bool ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsFunctionScan(FunctionScan *node);
-extern void ExecFunctionMarkPos(FunctionScan *node);
-extern void ExecFunctionRestrPos(FunctionScan *node);
-extern void ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent);
+extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate);
+extern TupleTableSlot *ExecFunctionScan(FunctionScanState *node);
+extern void ExecEndFunctionScan(FunctionScanState *node);
+extern void ExecFunctionMarkPos(FunctionScanState *node);
+extern void ExecFunctionRestrPos(FunctionScanState *node);
+extern void ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt);
 
 #endif   /* NODEFUNCTIONSCAN_H */
index b3c4e5b..211e55b 100644 (file)
@@ -7,20 +7,20 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeGroup.h,v 1.22 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeGroup.h,v 1.23 2002/12/05 15:50:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEGROUP_H
 #define NODEGROUP_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecGroup(Group *node);
-extern bool ExecInitGroup(Group *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsGroup(Group *node);
-extern void ExecEndGroup(Group *node);
-extern void ExecReScanGroup(Group *node, ExprContext *exprCtxt, Plan *parent);
+extern GroupState *ExecInitGroup(Group *node, EState *estate);
+extern TupleTableSlot *ExecGroup(GroupState *node);
+extern void ExecEndGroup(GroupState *node);
+extern void ExecReScanGroup(GroupState *node, ExprContext *exprCtxt);
 
 extern bool execTuplesMatch(HeapTuple tuple1,
                                HeapTuple tuple2,
index 654906c..c30073e 100644 (file)
@@ -7,19 +7,21 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeHash.h,v 1.26 2002/11/30 00:08:20 tgl Exp $
+ * $Id: nodeHash.h,v 1.27 2002/12/05 15:50:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEHASH_H
 #define NODEHASH_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecHash(Hash *node);
-extern bool ExecInitHash(Hash *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsHash(Hash *node);
-extern void ExecEndHash(Hash *node);
+extern HashState *ExecInitHash(Hash *node, EState *estate);
+extern TupleTableSlot *ExecHash(HashState *node);
+extern void ExecEndHash(HashState *node);
+extern void ExecReScanHash(HashState *node, ExprContext *exprCtxt);
+
 extern HashJoinTable ExecHashTableCreate(Hash *node);
 extern void ExecHashTableDestroy(HashJoinTable hashtable);
 extern void ExecHashTableInsert(HashJoinTable hashtable,
@@ -31,7 +33,6 @@ extern int ExecHashGetBucket(HashJoinTable hashtable,
 extern HeapTuple ExecScanHashBucket(HashJoinState *hjstate, List *hjclauses,
                                   ExprContext *econtext);
 extern void ExecHashTableReset(HashJoinTable hashtable, long ntuples);
-extern void ExecReScanHash(Hash *node, ExprContext *exprCtxt, Plan *parent);
 extern void ExecChooseHashTableSize(double ntuples, int tupwidth,
                                                int *virtualbuckets,
                                                int *physicalbuckets,
index d13a8c9..9233c07 100644 (file)
@@ -7,20 +7,21 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeHashjoin.h,v 1.23 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeHashjoin.h,v 1.24 2002/12/05 15:50:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEHASHJOIN_H
 #define NODEHASHJOIN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecHashJoin(HashJoin *node);
-extern bool ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsHashJoin(HashJoin *node);
-extern void ExecEndHashJoin(HashJoin *node);
+extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate);
+extern TupleTableSlot *ExecHashJoin(HashJoinState *node);
+extern void ExecEndHashJoin(HashJoinState *node);
+extern void ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt);
+
 extern void ExecHashJoinSaveTuple(HeapTuple heapTuple, BufFile *file);
-extern void ExecReScanHashJoin(HashJoin *node, ExprContext *exprCtxt, Plan *parent);
 
 #endif   /* NODEHASHJOIN_H */
index 26596e5..392807c 100644 (file)
@@ -7,22 +7,23 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeIndexscan.h,v 1.16 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeIndexscan.h,v 1.17 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEINDEXSCAN_H
 #define NODEINDEXSCAN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecIndexScan(IndexScan *node);
-extern void ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent);
-extern void ExecEndIndexScan(IndexScan *node);
-extern void ExecIndexMarkPos(IndexScan *node);
-extern void ExecIndexRestrPos(IndexScan *node);
-extern void ExecUpdateIndexScanKeys(IndexScan *node, ExprContext *econtext);
-extern bool ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsIndexScan(IndexScan *node);
+extern IndexScanState *ExecInitIndexScan(IndexScan *node, EState *estate);
+extern TupleTableSlot *ExecIndexScan(IndexScanState *node);
+extern void ExecEndIndexScan(IndexScanState *node);
+extern void ExecIndexMarkPos(IndexScanState *node);
+extern void ExecIndexRestrPos(IndexScanState *node);
+extern void ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt);
+
+extern void ExecUpdateIndexScanKeys(IndexScanState *node, ExprContext *econtext);
 
 #endif   /* NODEINDEXSCAN_H */
index 16fa607..5b50335 100644 (file)
@@ -7,19 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeLimit.h,v 1.6 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeLimit.h,v 1.7 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODELIMIT_H
 #define NODELIMIT_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecLimit(Limit *node);
-extern bool ExecInitLimit(Limit *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsLimit(Limit *node);
-extern void ExecEndLimit(Limit *node);
-extern void ExecReScanLimit(Limit *node, ExprContext *exprCtxt, Plan *parent);
+extern LimitState *ExecInitLimit(Limit *node, EState *estate);
+extern TupleTableSlot *ExecLimit(LimitState *node);
+extern void ExecEndLimit(LimitState *node);
+extern void ExecReScanLimit(LimitState *node, ExprContext *exprCtxt);
 
 #endif   /* NODELIMIT_H */
index 818fe75..8235bc8 100644 (file)
@@ -7,21 +7,21 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeMaterial.h,v 1.18 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeMaterial.h,v 1.19 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEMATERIAL_H
 #define NODEMATERIAL_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecMaterial(Material *node);
-extern bool ExecInitMaterial(Material *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsMaterial(Material *node);
-extern void ExecEndMaterial(Material *node);
-extern void ExecMaterialMarkPos(Material *node);
-extern void ExecMaterialRestrPos(Material *node);
-extern void ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent);
+extern MaterialState *ExecInitMaterial(Material *node, EState *estate);
+extern TupleTableSlot *ExecMaterial(MaterialState *node);
+extern void ExecEndMaterial(MaterialState *node);
+extern void ExecMaterialMarkPos(MaterialState *node);
+extern void ExecMaterialRestrPos(MaterialState *node);
+extern void ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt);
 
 #endif   /* NODEMATERIAL_H */
index b7ed7cd..1187d6b 100644 (file)
@@ -7,19 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeMergejoin.h,v 1.17 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeMergejoin.h,v 1.18 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEMERGEJOIN_H
 #define NODEMERGEJOIN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecMergeJoin(MergeJoin *node);
-extern bool ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsMergeJoin(MergeJoin *node);
-extern void ExecEndMergeJoin(MergeJoin *node);
-extern void ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent);
+extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate);
+extern TupleTableSlot *ExecMergeJoin(MergeJoinState *node);
+extern void ExecEndMergeJoin(MergeJoinState *node);
+extern void ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt);
 
-#endif   /* NODEMERGEJOIN_H; */
+#endif   /* NODEMERGEJOIN_H */
index e622475..fd48820 100644 (file)
@@ -7,20 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeNestloop.h,v 1.18 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeNestloop.h,v 1.19 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODENESTLOOP_H
 #define NODENESTLOOP_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecNestLoop(NestLoop *node);
-extern bool ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsNestLoop(NestLoop *node);
-extern void ExecEndNestLoop(NestLoop *node);
-extern void ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt,
-                                  Plan *parent);
+extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate);
+extern TupleTableSlot *ExecNestLoop(NestLoopState *node);
+extern void ExecEndNestLoop(NestLoopState *node);
+extern void ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt);
 
 #endif   /* NODENESTLOOP_H */
index 5d90cda..8a44640 100644 (file)
@@ -7,19 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeResult.h,v 1.15 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeResult.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODERESULT_H
 #define NODERESULT_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecResult(Result *node);
-extern bool ExecInitResult(Result *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsResult(Result *node);
-extern void ExecEndResult(Result *node);
-extern void ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent);
+extern ResultState *ExecInitResult(Result *node, EState *estate);
+extern TupleTableSlot *ExecResult(ResultState *node);
+extern void ExecEndResult(ResultState *node);
+extern void ExecReScanResult(ResultState *node, ExprContext *exprCtxt);
 
 #endif   /* NODERESULT_H */
index 86d591c..683c4ab 100644 (file)
@@ -7,21 +7,21 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeSeqscan.h,v 1.15 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeSeqscan.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODESEQSCAN_H
 #define NODESEQSCAN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecSeqScan(SeqScan *node);
-extern bool ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsSeqScan(SeqScan *node);
-extern void ExecEndSeqScan(SeqScan *node);
-extern void ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent);
-extern void ExecSeqMarkPos(SeqScan *node);
-extern void ExecSeqRestrPos(SeqScan *node);
+extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate);
+extern TupleTableSlot *ExecSeqScan(SeqScanState *node);
+extern void ExecEndSeqScan(SeqScanState *node);
+extern void ExecSeqMarkPos(SeqScanState *node);
+extern void ExecSeqRestrPos(SeqScanState *node);
+extern void ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt);
 
 #endif   /* NODESEQSCAN_H */
index eb1b8c2..73b1e7f 100644 (file)
@@ -7,19 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeSetOp.h,v 1.6 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeSetOp.h,v 1.7 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODESETOP_H
 #define NODESETOP_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecSetOp(SetOp *node);
-extern bool ExecInitSetOp(SetOp *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsSetOp(SetOp *node);
-extern void ExecEndSetOp(SetOp *node);
-extern void ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent);
+extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate);
+extern TupleTableSlot *ExecSetOp(SetOpState *node);
+extern void ExecEndSetOp(SetOpState *node);
+extern void ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt);
 
 #endif   /* NODESETOP_H */
index ca2d1d5..7836b32 100644 (file)
@@ -7,21 +7,21 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeSort.h,v 1.15 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeSort.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODESORT_H
 #define NODESORT_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecSort(Sort *node);
-extern bool ExecInitSort(Sort *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsSort(Sort *node);
-extern void ExecEndSort(Sort *node);
-extern void ExecSortMarkPos(Sort *node);
-extern void ExecSortRestrPos(Sort *node);
-extern void ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent);
+extern SortState *ExecInitSort(Sort *node, EState *estate);
+extern TupleTableSlot *ExecSort(SortState *node);
+extern void ExecEndSort(SortState *node);
+extern void ExecSortMarkPos(SortState *node);
+extern void ExecSortRestrPos(SortState *node);
+extern void ExecReScanSort(SortState *node, ExprContext *exprCtxt);
 
 #endif   /* NODESORT_H */
index a061a42..c573cf9 100644 (file)
@@ -2,18 +2,26 @@
  *
  * nodeSubplan.h
  *
+ *
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: nodeSubplan.h,v 1.12 2002/12/05 15:50:38 tgl Exp $
+ *
  *-------------------------------------------------------------------------
  */
 #ifndef NODESUBPLAN_H
 #define NODESUBPLAN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern Datum ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext,
+extern SubPlanState *ExecInitSubPlan(SubPlan *node, EState *estate);
+extern Datum ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext,
                        bool *isNull);
-extern bool ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent);
-extern void ExecReScanSetParamPlan(SubPlan *node, Plan *parent);
-extern void ExecSetParamPlan(SubPlan *node, ExprContext *econtext);
-extern void ExecEndSubPlan(SubPlan *node);
+extern void ExecEndSubPlan(SubPlanState *node);
+extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
+
+extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
 
 #endif   /* NODESUBPLAN_H */
index e1a5f01..5c5d5c8 100644 (file)
@@ -7,19 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeSubqueryscan.h,v 1.6 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeSubqueryscan.h,v 1.7 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODESUBQUERYSCAN_H
 #define NODESUBQUERYSCAN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecSubqueryScan(SubqueryScan *node);
-extern void ExecEndSubqueryScan(SubqueryScan *node);
-extern bool ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsSubqueryScan(SubqueryScan *node);
-extern void ExecSubqueryReScan(SubqueryScan *node, ExprContext *exprCtxt, Plan *parent);
+extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate);
+extern TupleTableSlot *ExecSubqueryScan(SubqueryScanState *node);
+extern void ExecEndSubqueryScan(SubqueryScanState *node);
+extern void ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt);
 
 #endif   /* NODESUBQUERYSCAN_H */
index 72e6c3e..9aadb59 100644 (file)
@@ -7,22 +7,21 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeTidscan.h,v 1.10 2002/11/30 05:21:03 tgl Exp $
+ * $Id: nodeTidscan.h,v 1.11 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODETIDSCAN_H
 #define NODETIDSCAN_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecTidScan(TidScan *node);
-extern void ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent);
-extern void ExecEndTidScan(TidScan *node);
-extern void ExecTidMarkPos(TidScan *node);
-extern void ExecTidRestrPos(TidScan *node);
-extern bool ExecInitTidScan(TidScan *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsTidScan(TidScan *node);
-extern void ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent);
+extern TidScanState *ExecInitTidScan(TidScan *node, EState *estate);
+extern TupleTableSlot *ExecTidScan(TidScanState *node);
+extern void ExecEndTidScan(TidScanState *node);
+extern void ExecTidMarkPos(TidScanState *node);
+extern void ExecTidRestrPos(TidScanState *node);
+extern void ExecTidReScan(TidScanState *node, ExprContext *exprCtxt);
 
 #endif   /* NODETIDSCAN_H */
index f829b65..d71997e 100644 (file)
@@ -7,19 +7,19 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeUnique.h,v 1.15 2002/06/20 20:29:49 momjian Exp $
+ * $Id: nodeUnique.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEUNIQUE_H
 #define NODEUNIQUE_H
 
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
-extern TupleTableSlot *ExecUnique(Unique *node);
-extern bool ExecInitUnique(Unique *node, EState *estate, Plan *parent);
 extern int     ExecCountSlotsUnique(Unique *node);
-extern void ExecEndUnique(Unique *node);
-extern void ExecReScanUnique(Unique *node, ExprContext *exprCtxt, Plan *parent);
+extern UniqueState *ExecInitUnique(Unique *node, EState *estate);
+extern TupleTableSlot *ExecUnique(UniqueState *node);
+extern void ExecEndUnique(UniqueState *node);
+extern void ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt);
 
 #endif   /* NODEUNIQUE_H */
index 5445107..a4f10ef 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: execnodes.h,v 1.81 2002/11/30 00:08:20 tgl Exp $
+ * $Id: execnodes.h,v 1.82 2002/12/05 15:50:38 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/params.h"
-#include "nodes/primnodes.h"
+#include "nodes/plannodes.h"
 #include "utils/tuplestore.h"
 
 
@@ -316,6 +315,8 @@ typedef struct EState
        List       *es_rowMark;         /* not good place, but there is no other */
        MemoryContext es_query_cxt; /* per-query context in which EState lives */
 
+       bool            es_instrument;  /* true requests runtime instrumentation */
+
        /*
         * this ExprContext is for per-output-tuple operations, such as
         * constraint checks and index-value computations.      It will be reset
@@ -332,98 +333,101 @@ typedef struct EState
        bool            es_useEvalPlan;
 } 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 preceding 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
- * ----------------
- */
 
 /* ----------------------------------------------------------------
- *                              Common Executor State Information
+ *                              Executor State Information
  * ----------------------------------------------------------------
  */
 
 /* ----------------
- *      CommonState information
- *
- *             Superclass for all executor node-state object types.
+ *             PlanState 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?)
+ * We never actually instantiate any PlanState nodes; this is just the common
+ * abstract superclass for all PlanState-type nodes.
  * ----------------
  */
-typedef struct CommonState
+typedef struct PlanState
 {
-       NodeTag         type;                   /* its first field is NodeTag */
-       TupleTableSlot *cs_OuterTupleSlot;
-       TupleTableSlot *cs_ResultTupleSlot;
-       ExprContext *cs_ExprContext;
-       ProjectionInfo *cs_ProjInfo;
-       bool            cs_TupFromTlist;
-} CommonState;
+       NodeTag         type;
 
+       Plan       *plan;                       /* associated Plan node */
 
-/* ----------------------------------------------------------------
- *                              Control Node State Information
- * ----------------------------------------------------------------
+       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
+        */
+       List       *chgParam;           /* integer list 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
- *
- *             done                       flag which tells us to quit when we
- *                                                have already returned a constant tuple.
  * ----------------
  */
 typedef struct ResultState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
-       bool            rs_done;
-       bool            rs_checkqual;
+       PlanState       ps;                             /* its first field is NodeTag */
+       Node       *resconstantqual;
+       bool            rs_done;                /* are we done? */
+       bool            rs_checkqual;   /* do we need to check the qual? */
 } ResultState;
 
 /* ----------------
  *      AppendState information
  *
+ *             nplans                  how many plans are in the list
  *             whichplan               which plan is being executed (0 .. n-1)
  *             firstplan               first plan to execute (usually 0)
  *             lastplan                last plan to execute (usually n-1)
- *             nplans                  how many plans are in the list
- *             initialized             array of ExecInitNode() results
  * ----------------
  */
 typedef struct AppendState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
+       PlanState       ps;                             /* its first field is NodeTag */
+       PlanState **appendplans;        /* array of PlanStates for my inputs */
+       int                     as_nplans;
        int                     as_whichplan;
        int                     as_firstplan;
        int                     as_lastplan;
-       int                     as_nplans;
-       bool       *as_initialized;
 } AppendState;
 
 /* ----------------------------------------------------------------
@@ -432,9 +436,9 @@ typedef struct AppendState
  */
 
 /* ----------------
- *      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
@@ -445,27 +449,23 @@ 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;
 
 /* ----------------
  *      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
@@ -479,7 +479,9 @@ typedef struct CommonScanState
  */
 typedef struct IndexScanState
 {
-       NodeTag         type;
+       ScanState       ss;                             /* its first field is NodeTag */
+       List       *indxqual;
+       List       *indxqualorig;
        int                     iss_NumIndices;
        int                     iss_IndexPtr;
        int                     iss_MarkIndexPtr;
@@ -495,10 +497,6 @@ typedef struct IndexScanState
 /* ----------------
  *      TidScanState 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.
- *
  *             NumTids            number of tids in this scan
  *             TidPtr             current tid in use
  *             TidList            evaluated item pointers
@@ -506,7 +504,7 @@ typedef struct IndexScanState
  */
 typedef struct TidScanState
 {
-       NodeTag         type;
+       ScanState       ss;                             /* its first field is NodeTag */
        int                     tss_NumTids;
        int                     tss_TidPtr;
        int                     tss_MarkTidPtr;
@@ -526,7 +524,8 @@ 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;
 
@@ -538,12 +537,12 @@ typedef struct SubqueryScanState
  *
  *             tupdesc                         expected return tuple description
  *             tuplestorestate         private state of tuplestore.c
- *             funcexpr                        function expression being evaluated
+ *             funcexpr                        state for function expression being evaluated
  * ----------------
  */
 typedef struct FunctionScanState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
+       ScanState       ss;                             /* its first field is NodeTag */
        TupleDesc       tupdesc;
        Tuplestorestate *tuplestorestate;
        Node       *funcexpr;
@@ -557,11 +556,15 @@ typedef struct FunctionScanState
 /* ----------------
  *      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
@@ -573,7 +576,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;
@@ -596,7 +599,8 @@ typedef struct NestLoopState
  */
 typedef struct MergeJoinState
 {
-       JoinState       jstate;                 /* its first field is NodeTag */
+       JoinState       js;                             /* its first field is NodeTag */
+       List       *mergeclauses;
        List       *mj_OuterSkipQual;
        List       *mj_InnerSkipQual;
        int                     mj_JoinState;
@@ -630,7 +634,8 @@ typedef struct MergeJoinState
  */
 typedef struct HashJoinState
 {
-       JoinState       jstate;                 /* its first field is NodeTag */
+       JoinState       js;                             /* its first field is NodeTag */
+       List       *hashclauses;
        HashJoinTable hj_HashTable;
        int                     hj_CurBucketNo;
        HashJoinTuple hj_CurTuple;
@@ -656,23 +661,46 @@ 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.
+ *             ss.ss_ScanTupleSlot refers to output of underlying plan.
  *
  *             tuplestorestate         private state of tuplestore.c
  * ----------------
  */
 typedef struct MaterialState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
+       ScanState       ss;                             /* its first field is NodeTag */
        void       *tuplestorestate;
 } MaterialState;
 
+/* ----------------
+ *      SortState information
+ * ----------------
+ */
+typedef struct SortState
+{
+       ScanState       ss;                             /* its first field is NodeTag */
+       bool            sort_Done;              /* sort completed yet? */
+       void       *tuplesortstate;     /* private state of tuplesort.c */
+} SortState;
+
 /* ---------------------
- *     AggregateState information
+ *     GroupState information
+ * -------------------------
+ */
+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;
+
+/* ---------------------
+ *     AggState information
  *
- *     csstate.css_ScanTupleSlot refers to output of underlying plan.
+ *     ss.ss_ScanTupleSlot refers to output of underlying plan.
  *
- *     Note: csstate.cstate.cs_ExprContext contains ecxt_aggvalues and
+ *     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
@@ -687,7 +715,7 @@ typedef struct AggHashTableData *AggHashTable;
 
 typedef struct AggState
 {
-       CommonScanState csstate;        /* its first field is NodeTag */
+       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 */
@@ -705,32 +733,6 @@ typedef struct AggState
        int                     next_hash_bucket; /* next chain */
 } AggState;
 
-/* ---------------------
- *     GroupState information
- * -------------------------
- */
-typedef struct GroupState
-{
-       CommonScanState csstate;        /* 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;
-
-/* ----------------
- *      SortState information
- *
- *             sort_Done               indicates whether sort has been performed yet
- *             tuplesortstate  private state of tuplesort.c
- * ----------------
- */
-typedef struct SortState
-{
-       CommonScanState csstate;        /* its first field is NodeTag */
-       bool            sort_Done;
-       void       *tuplesortstate;
-} SortState;
-
 /* ----------------
  *      UniqueState information
  *
@@ -744,13 +746,23 @@ typedef struct SortState
  */
 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 */
+} HashState;
+
+/* ----------------
  *      SetOpState information
  *
  *             SetOp nodes are used "on top of" sort nodes to discard
@@ -761,7 +773,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 */
@@ -794,7 +806,9 @@ typedef enum
 
 typedef struct LimitState
 {
-       CommonState cstate;                     /* its first field is NodeTag */
+       PlanState       ps;                             /* its first field is NodeTag */
+       Node       *limitOffset;        /* OFFSET parameter, or NULL if none */
+       Node       *limitCount;         /* COUNT parameter, or NULL if none */
        long            offset;                 /* current OFFSET value */
        long            count;                  /* current COUNT, if any */
        bool            noCount;                /* if true, ignore count */
@@ -803,46 +817,16 @@ typedef struct LimitState
        TupleTableSlot *subSlot;        /* tuple last obtained from subplan */
 } LimitState;
 
-
-/* ----------------
- *      HashState information
- *
- *             hashtable                       hash table for the hashjoin
- * ----------------
+/* ---------------------
+ *      SubPlanState information
+ * ---------------------
  */
-typedef struct HashState
+typedef struct SubPlanState
 {
-       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
+       PlanState       ps;                             /* its first field is NodeTag */
+       PlanState  *planstate;          /* subselect plan's state tree */
+       bool            needShutdown;   /* TRUE = need to shutdown subplan */
+       HeapTuple       curTuple;               /* copy of most recent tuple from subplan */
+} SubPlanState;
 
 #endif   /* EXECNODES_H */
index a9cd095..cb16a30 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.125 2002/11/30 05:21:03 tgl Exp $
+ * $Id: nodes.h,v 1.126 2002/12/05 15:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * The first field of every node is NodeTag. Each node created (with makeNode)
  * will have one of the following tags as the value of its first field.
  *
- * Note that the number of the node tags are not contiguous. We left holes
+ * Note that the numbers of the node tags are not contiguous. We left holes
  * here so that we can add more tags without changing the existing enum's.
+ * (Since node tag numbers never exist outside backend memory, there's no
+ * real harm in renumbering, it just costs a full rebuild ...)
  */
 typedef enum NodeTag
 {
        T_Invalid = 0,
 
        /*
+        * TAGS FOR EXECUTOR NODES (execnodes.h)
+        */
+       T_IndexInfo = 10,
+       T_ResultRelInfo,
+       T_TupleTableSlot,
+       T_ExprContext,
+       T_ProjectionInfo,
+       T_JunkFilter,
+       T_EState,
+
+       /*
         * TAGS FOR PLAN NODES (plannodes.h)
         */
-       T_Plan = 10,
+       T_Plan = 100,
        T_Result,
        T_Append,
        T_Scan,
        T_SeqScan,
        T_IndexScan,
+       T_TidScan,
+       T_SubqueryScan,
+       T_FunctionScan,
        T_Join,
        T_NestLoop,
        T_MergeJoin,
        T_HashJoin,
-       T_Limit,
        T_Material,
        T_Sort,
+       T_Group,
        T_Agg,
        T_Unique,
        T_Hash,
        T_SetOp,
-       T_Group,
+       T_Limit,
        T_SubPlan,
-       T_TidScan,
-       T_SubqueryScan,
-       T_FunctionScan,
+
+       /*
+        * TAGS FOR PLAN STATE NODES (execnodes.h)
+        *
+        * These should correspond one-to-one with Plan node types.
+        */
+       T_PlanState = 200,
+       T_ResultState,
+       T_AppendState,
+       T_ScanState,
+       T_SeqScanState,
+       T_IndexScanState,
+       T_TidScanState,
+       T_SubqueryScanState,
+       T_FunctionScanState,
+       T_JoinState,
+       T_NestLoopState,
+       T_MergeJoinState,
+       T_HashJoinState,
+       T_MaterialState,
+       T_SortState,
+       T_GroupState,
+       T_AggState,
+       T_UniqueState,
+       T_HashState,
+       T_SetOpState,
+       T_LimitState,
+       T_SubPlanState,
 
        /*
         * TAGS FOR PRIMITIVE NODES (primnodes.h)
         */
-       T_Resdom = 100,
+       T_Resdom = 300,
        T_Fjoin,
        T_Expr,
        T_Var,
@@ -74,7 +115,7 @@ typedef enum NodeTag
        /*
         * TAGS FOR PLANNER NODES (relation.h)
         */
-       T_RelOptInfo = 200,
+       T_RelOptInfo = 400,
        T_IndexOptInfo,
        T_Path,
        T_IndexPath,
@@ -91,47 +132,15 @@ typedef enum NodeTag
        T_InnerIndexscanInfo,
 
        /*
-        * TAGS FOR EXECUTOR NODES (execnodes.h)
-        */
-       T_IndexInfo = 300,
-       T_ResultRelInfo,
-       T_TupleTableSlot,
-       T_ExprContext,
-       T_ProjectionInfo,
-       T_JunkFilter,
-       T_EState,
-       T_CommonState,
-       T_ResultState,
-       T_AppendState,
-       T_CommonScanState,
-       T_ScanState,
-       T_IndexScanState,
-       T_JoinState,
-       T_NestLoopState,
-       T_MergeJoinState,
-       T_HashJoinState,
-       T_MaterialState,
-       T_AggState,
-       T_GroupState,
-       T_SortState,
-       T_UniqueState,
-       T_HashState,
-       T_TidScanState,
-       T_SubqueryScanState,
-       T_SetOpState,
-       T_LimitState,
-       T_FunctionScanState,
-
-       /*
         * TAGS FOR MEMORY NODES (memnodes.h)
         */
-       T_MemoryContext = 400,
+       T_MemoryContext = 500,
        T_AllocSetContext,
 
        /*
         * TAGS FOR VALUE NODES (pg_list.h)
         */
-       T_Value = 500,
+       T_Value = 600,
        T_List,
        T_Integer,
        T_Float,
@@ -142,7 +151,7 @@ typedef enum NodeTag
        /*
         * TAGS FOR PARSE TREE NODES (parsenodes.h)
         */
-       T_Query = 600,
+       T_Query = 700,
        T_InsertStmt,
        T_DeleteStmt,
        T_UpdateStmt,
@@ -208,7 +217,7 @@ typedef enum NodeTag
        T_ExecuteStmt,
        T_DeallocateStmt,
 
-       T_A_Expr = 700,
+       T_A_Expr = 800,
        T_ColumnRef,
        T_ParamRef,
        T_A_Const,
@@ -248,7 +257,7 @@ typedef enum NodeTag
        /*
         * TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
         */
-       T_TriggerData = 800,            /* in commands/trigger.h */
+       T_TriggerData = 900,            /* in commands/trigger.h */
        T_ReturnSetInfo                         /* in nodes/execnodes.h */
 
 } NodeTag;
index ef0e068..8f2eff5 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: params.h,v 1.18 2002/11/25 21:29:42 tgl Exp $
+ * $Id: params.h,v 1.19 2002/12/05 15:50:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -88,7 +88,7 @@ typedef ParamListInfoData *ParamListInfo;
  *       array of ParamExecData records, which is referenced through
  *       es_param_exec_vals or ecxt_param_exec_vals.
  *
- *       If execPlan is not NULL, it points to a SubPlan node that needs to
+ *       If execPlan is not NULL, it points to a SubPlanState node that needs to
  *       be executed to produce the value.  (This is done so that we can have
  *       lazy evaluation of InitPlans: they aren't executed until/unless a
  *       result value is needed.)  Otherwise the value is assumed to be valid
@@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo;
 
 typedef struct ParamExecData
 {
-       void       *execPlan;           /* should be "SubPlan *" */
+       void       *execPlan;           /* should be "SubPlanState *" */
        Datum           value;
        bool            isnull;
 } ParamExecData;
index 6a6ac41..097f8d9 100644 (file)
@@ -7,52 +7,15 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: plannodes.h,v 1.61 2002/11/30 00:08:22 tgl Exp $
+ * $Id: plannodes.h,v 1.62 2002/12/05 15:50:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef PLANNODES_H
 #define PLANNODES_H
 
-#include "nodes/execnodes.h"
-
-/* ----------------------------------------------------------------
- *     Executor State types are used in the plannode structures
- *     so we have to include their definitions too.
- *
- *             Node Type                               node information used by executor
- *
- * control nodes
- *
- *             Result                                  ResultState                             resstate;
- *             Append                                  AppendState                             appendstate;
- *
- * scan nodes
- *
- *             Scan ***                                CommonScanState                 scanstate;
- *             IndexScan                               IndexScanState                  indxstate;
- *             SubqueryScan                    SubqueryScanState               subquerystate;
- *             FunctionScan                    FunctionScanState               functionstate;
- *
- *               (*** nodes which inherit Scan also inherit scanstate)
- *
- * join nodes
- *
- *             NestLoop                                NestLoopState                   nlstate;
- *             MergeJoin                               MergeJoinState                  mergestate;
- *             HashJoin                                HashJoinState                   hashjoinstate;
- *
- * materialize nodes
- *
- *             Material                                MaterialState                   matstate;
- *             Sort                                    SortState                               sortstate;
- *             Unique                                  UniqueState                             uniquestate;
- *             SetOp                                   SetOpState                              setopstate;
- *             Limit                                   LimitState                              limitstate;
- *             Hash                                    HashState                               hashstate;
- *
- * ----------------------------------------------------------------
- */
+#include "access/sdir.h"
+#include "nodes/primnodes.h"
 
 
 /* ----------------------------------------------------------------
 
 /* ----------------
  *             Plan node
+ *
+ * All plan nodes "derive" from the Plan structure by having the
+ * Plan structure as the first field.  This ensures that everything works
+ * when nodes are cast to Plan's.  (node pointers are frequently cast to Plan*
+ * when passed around generically in the executor)
+ *
+ * We never actually instantiate any Plan nodes; this is just the common
+ * abstract superclass for all Plan-type nodes.
  * ----------------
  */
-
 typedef struct Plan
 {
        NodeTag         type;
 
-       /* estimated execution costs for plan (see costsize.c for more info) */
+       /*
+        * estimated execution costs for plan (see costsize.c for more info)
+        */
        Cost            startup_cost;   /* cost expended before fetching any
                                                                 * tuples */
        Cost            total_cost;             /* total cost (assuming all tuples
                                                                 * fetched) */
 
        /*
-        * planner's estimate of result size (note: LIMIT, if any, is not
-        * considered in setting plan_rows)
+        * planner's estimate of result size of this plan step
         */
        double          plan_rows;              /* number of rows plan is expected to emit */
        int                     plan_width;             /* average row width in bytes */
 
        /*
-        * execution state data.  Having Plan point to this, rather than the
-        * other way round, is 100% bogus.
+        * Common structural data for all Plan types.
         */
-       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 */
+       List       *targetlist;         /* target list to be computed at this node */
+       List       *qual;                       /* implicitly-ANDed qual conditions */
+       struct Plan *lefttree;          /* input plan tree(s) */
+       struct Plan *righttree;
+       List       *initPlan;           /* Init Plan nodes (un-correlated expr
+                                                                * subselects) */
 
        /*
-        * Common structural data for all Plan types.  XXX chgParam is runtime
-        * data and should be in the EState, not here.
+        * Information for management of parameter-change-driven rescanning
         */
-       List       *targetlist;
-       List       *qual;                       /* implicitly-ANDed qual conditions */
-       struct Plan *lefttree;
-       struct Plan *righttree;
        List       *extParam;           /* indices of _all_ _external_ PARAM_EXEC
                                                                 * for this plan in global
                                                                 * es_param_exec_vals. Params from
@@ -108,10 +73,6 @@ typedef struct Plan
                                                                 * included, but their execParam-s are
                                                                 * here!!! */
        List       *locParam;           /* someones from setParam-s */
-       List       *chgParam;           /* list of changed ones from the above */
-       List       *initPlan;           /* Init Plan nodes (un-correlated expr
-                                                                * subselects) */
-       List       *subPlan;            /* Other SubPlan nodes */
 
        /*
         * We really need in some TopPlan node to store range table and
@@ -134,20 +95,6 @@ typedef struct Plan
 #define outerPlan(node)                        (((Plan *)(node))->lefttree)
 
 
-/*
- * ===============
- * Top-level nodes
- * ===============
- */
-
-/*
- * all plan nodes "derive" from the Plan structure by having the
- * Plan structure as the first field.  This ensures that everything works
- * when nodes are cast to Plan's.  (node pointers are frequently cast to Plan*
- * when passed around generically in the executor)
- */
-
-
 /* ----------------
  *      Result node -
  *             If no outer plan, evaluate a variable-free targetlist.
@@ -163,7 +110,6 @@ typedef struct Result
 {
        Plan            plan;
        Node       *resconstantqual;
-       ResultState *resstate;
 } Result;
 
 /* ----------------
@@ -182,7 +128,6 @@ typedef struct Append
        Plan            plan;
        List       *appendplans;
        bool            isTarget;
-       AppendState *appendstate;
 } Append;
 
 /*
@@ -194,7 +139,6 @@ typedef struct Scan
 {
        Plan            plan;
        Index           scanrelid;              /* relid is index into the range table */
-       CommonScanState *scanstate;
 } Scan;
 
 /* ----------------
@@ -214,7 +158,6 @@ typedef struct IndexScan
        List       *indxqual;
        List       *indxqualorig;
        ScanDirection indxorderdir;
-       IndexScanState *indxstate;
 } IndexScan;
 
 /* ----------------
@@ -224,9 +167,7 @@ typedef struct IndexScan
 typedef struct TidScan
 {
        Scan            scan;
-       bool            needRescan;
        List       *tideval;
-       TidScanState *tidstate;
 } TidScan;
 
 /* ----------------
@@ -257,7 +198,6 @@ typedef struct FunctionScan
 {
        Scan            scan;
        /* no other fields needed at present */
-       /* scan.scanstate actually points at a FunctionScanState node */
 } FunctionScan;
 
 /*
@@ -296,7 +236,6 @@ typedef struct Join
 typedef struct NestLoop
 {
        Join            join;
-       NestLoopState *nlstate;
 } NestLoop;
 
 /* ----------------
@@ -307,7 +246,6 @@ typedef struct MergeJoin
 {
        Join            join;
        List       *mergeclauses;
-       MergeJoinState *mergestate;
 } MergeJoin;
 
 /* ----------------
@@ -318,9 +256,40 @@ typedef struct HashJoin
 {
        Join            join;
        List       *hashclauses;
-       HashJoinState *hashjoinstate;
 } HashJoin;
 
+/* ----------------
+ *             materialization node
+ * ----------------
+ */
+typedef struct Material
+{
+       Plan            plan;
+} Material;
+
+/* ----------------
+ *             sort node
+ * ----------------
+ */
+typedef struct Sort
+{
+       Plan            plan;
+       int                     keycount;
+} Sort;
+
+/* ---------------
+ *      group node -
+ *             Used for queries with GROUP BY (but no aggregates) specified.
+ *             The input must be presorted according to the grouping columns.
+ * ---------------
+ */
+typedef struct Group
+{
+       Plan            plan;
+       int                     numCols;                /* number of grouping columns */
+       AttrNumber *grpColIdx;          /* their indexes in the target list */
+} Group;
+
 /* ---------------
  *             aggregate node
  *
@@ -349,44 +318,8 @@ typedef struct Agg
        int                     numCols;                /* number of grouping columns */
        AttrNumber *grpColIdx;          /* their indexes in the target list */
        long            numGroups;              /* estimated number of groups in input */
-       AggState   *aggstate;
 } Agg;
 
-/* ---------------
- *      group node -
- *             Used for queries with GROUP BY (but no aggregates) specified.
- *             The input must be presorted according to the grouping columns.
- * ---------------
- */
-typedef struct Group
-{
-       Plan            plan;
-       int                     numCols;                /* number of grouping columns */
-       AttrNumber *grpColIdx;          /* their indexes in the target list */
-       GroupState *grpstate;
-} Group;
-
-/* ----------------
- *             materialization node
- * ----------------
- */
-typedef struct Material
-{
-       Plan            plan;
-       MaterialState *matstate;
-} Material;
-
-/* ----------------
- *             sort node
- * ----------------
- */
-typedef struct Sort
-{
-       Plan            plan;
-       int                     keycount;
-       SortState  *sortstate;
-} Sort;
-
 /* ----------------
  *             unique node
  * ----------------
@@ -397,10 +330,19 @@ typedef struct Unique
        int                     numCols;                /* number of columns to check for
                                                                 * uniqueness */
        AttrNumber *uniqColIdx;         /* indexes into the target list */
-       UniqueState *uniquestate;
 } Unique;
 
 /* ----------------
+ *             hash build node
+ * ----------------
+ */
+typedef struct Hash
+{
+       Plan            plan;
+       List       *hashkeys;
+} Hash;
+
+/* ----------------
  *             setop node
  * ----------------
  */
@@ -420,7 +362,6 @@ typedef struct SetOp
                                                                 * duplicate-ness */
        AttrNumber *dupColIdx;          /* indexes into the target list */
        AttrNumber      flagColIdx;
-       SetOpState *setopstate;
 } SetOp;
 
 /* ----------------
@@ -432,44 +373,13 @@ typedef struct Limit
        Plan            plan;
        Node       *limitOffset;        /* OFFSET parameter, or NULL if none */
        Node       *limitCount;         /* COUNT parameter, or NULL if none */
-       LimitState *limitstate;
 } Limit;
 
-/* ----------------
- *             hash build node
- * ----------------
- */
-typedef struct Hash
-{
-       Plan            plan;
-       List       *hashkeys;
-       HashState  *hashstate;
-} Hash;
-
-#ifdef NOT_USED
-/* -------------------
- *             Tee node information
- *
- *       leftParent :                          the left parent of this node
- *       rightParent:                          the right parent of this node
- * -------------------
-*/
-typedef struct Tee
-{
-       Plan            plan;
-       Plan       *leftParent;
-       Plan       *rightParent;
-       TeeState   *teestate;
-       char       *teeTableName;       /* the name of the table to materialize
-                                                                * the tee into */
-       List       *rtentries;          /* the range table for the plan below the
-                                                                * Tee may be different than the parent
-                                                                * plans */
-}      Tee;
-#endif
-
 /* ---------------------
  *             SubPlan node
+ *
+ * XXX Perhaps does not belong in this file?  It's not really a Plan node.
+ * Should we make it inherit from Plan anyway?
  * ---------------------
  */
 typedef struct SubPlan
@@ -489,12 +399,7 @@ typedef struct SubPlan
                                                                 * about what to do with subselect's
                                                                 * results */
 
-       /*
-        * Remaining fields are working state for executor; not used in
-        * planning
-        */
-       bool            needShutdown;   /* TRUE = need to shutdown subplan */
-       HeapTuple       curTuple;               /* copy of most recent tuple from subplan */
+       struct SubPlanState *pstate; /* XXX TEMPORARY HACK */
 } SubPlan;
 
 #endif   /* PLANNODES_H */
index 7ebcef4..07accf7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: print.h,v 1.19 2002/09/04 20:31:44 momjian Exp $
+ * $Id: print.h,v 1.20 2002/12/05 15:50:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define PRINT_H
 
 #include "nodes/parsenodes.h"
-#include "nodes/plannodes.h"
+#include "nodes/execnodes.h"
 
 
-#define nodeDisplay            pprint
+#define nodeDisplay(x)         pprint(x)
 
 extern void print(void *obj);
 extern void pprint(void *obj);
index 5f6ad68..333ca0b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relation.h,v 1.72 2002/11/30 05:21:03 tgl Exp $
+ * $Id: relation.h,v 1.73 2002/12/05 15:50:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -377,8 +377,7 @@ typedef struct IndexPath
 typedef struct TidPath
 {
        Path            path;
-       List       *tideval;                    /* qual(s) involving CTID = something */
-       Relids          unjoined_relids;        /* some rels not yet part of my Path */
+       List       *tideval;            /* qual(s) involving CTID = something */
 } TidPath;
 
 /*
index a29b185..b001424 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pquery.h,v 1.22 2002/09/04 20:31:45 momjian Exp $
+ * $Id: pquery.h,v 1.23 2002/12/05 15:50:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,8 +21,6 @@
 extern void ProcessQuery(Query *parsetree, Plan *plan, CommandDest dest,
                         char *completionTag);
 
-extern EState *CreateExecutorState(void);
-
 extern Portal PreparePortal(char *portalName);
 
 #endif   /* PQUERY_H */
index ba784fe..40258ac 100644 (file)
@@ -3,19 +3,16 @@
  * portal.h
  *       POSTGRES portal definitions.
  *
+ * A portal is an abstraction which represents the execution state of
+ * a running query (specifically, a CURSOR).
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: portal.h,v 1.35 2002/09/04 20:31:45 momjian Exp $
+ * $Id: portal.h,v 1.36 2002/12/05 15:50:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
-/*
- * Note:
- *             A portal is an abstraction which represents the execution state of
- * a running query (specifically, a CURSOR).
- */
 #ifndef PORTAL_H
 #define PORTAL_H
 
@@ -30,8 +27,6 @@ typedef struct PortalData
        char       *name;                       /* Portal's name */
        MemoryContext heap;                     /* subsidiary memory */
        QueryDesc  *queryDesc;          /* Info about query associated with portal */
-       TupleDesc       attinfo;
-       EState     *state;                      /* Execution state of query */
        bool            atStart;                /* T => fetch backwards is not allowed */
        bool            atEnd;                  /* T => fetch forwards is not allowed */
        void            (*cleanup) (Portal);    /* Cleanup routine (optional) */
@@ -47,8 +42,6 @@ typedef struct PortalData
  * Access macros for Portal ... use these in preference to field access.
  */
 #define PortalGetQueryDesc(portal)     ((portal)->queryDesc)
-#define PortalGetTupleDesc(portal)     ((portal)->attinfo)
-#define PortalGetState(portal)         ((portal)->state)
 #define PortalGetHeapMemory(portal) ((portal)->heap)
 
 /*
@@ -64,7 +57,6 @@ extern Portal CreatePortal(char *name);
 extern void PortalDrop(Portal portal);
 extern Portal GetPortalByName(char *name);
 extern void PortalSetQuery(Portal portal, QueryDesc *queryDesc,
-                          TupleDesc attinfo, EState *state,
-                          void (*cleanup) (Portal portal));
+                                                  void (*cleanup) (Portal portal));
 
 #endif   /* PORTAL_H */
index 2bdf241..007a3ff 100644 (file)
@@ -3,7 +3,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.71 2002/11/30 21:25:08 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.72 2002/12/05 15:50:39 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -3583,7 +3583,6 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
        if (plan->lefttree != NULL ||
                plan->righttree != NULL ||
                plan->initPlan != NULL ||
-               plan->subPlan != NULL ||
                plan->qual != NULL ||
                ((Result *) plan)->resconstantqual != NULL)
                return;