Phase 1 of read-only-plans project: cause executor state nodes to point
authorTom Lane
Thu, 5 Dec 2002 15:50:39 +0000 (15:50 +0000)
committerTom Lane
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 0e6ca88fd4549473caef78d809c5d55641312938..e2d1a6eeab1307fa86330df4539b6b3a5de791b6 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 812cb05dacfb90930e448dbb5b003f23fb80ac38..c8607fcf3244dbbf1a6e9f7453bc886cbd041b52 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 391ef0bc9c5dbcdff6e66c9072057fb28c55adbe..9a570c8f6816a2f3ea348e438ef53bb59a586c27 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 0a56c3fa6ae550ab654b246021d435ad6b53719d..d9b0ea1275a1c2f1f44d6d27748c6eabe695792b 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 1d7bf67f60b6b111d100b5da81bcb18a6f2acbc2..4ac4781ec7cf0654e9aefb6d3a44360f8a1bcaac 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 92026666894f2da54f73e304fc784d22b5317878..15d47df669f38c7096fa8cc3ee15603f21555fb3 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 2054a6cf059426967082fcbe17b21ebd0948de78..2db4a146bc16cefb8ff3e58eba817b2bc9c0a60b 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 cb31c025df24878c8ae6388e36719f47fe384f31..e7c724c66ed979b3ed1370409cd86652176bc7d1 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 9fd7c4fb00c01abb7568d8f0979fbf5aad22acc3..6944e03e9bcfa24deca6b6a4a513ee17bac02112 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 7b0df664c7468ed6b9f32f5535baddf443d82231..f5a6863b1ac77e736e7f18f6072cd1e0611a4599 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 86440d10f9e8f00bc3f88472a90dba92c9c760e7..0dd17b7965bde211fe53be217a8dd862f738dc76 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 71166d9096c3c11a7c82b00fe9a7fbde0e5458db..328aea5f07992c19b4c1d273f6023d3978c692dc 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)
@@ -481,6 +469,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.
     */
@@ -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 82e9f48e1e0ef069ab78510244b7695bd1f8236b..bdbe61cb10ac94d2bf50f0a2bbbc6fd480da7d1f 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;
@@ -1094,16 +1088,15 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
                aggno;
    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;
@@ -1111,38 +1104,14 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
    aggstate->grp_firstTuple = NULL;
    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
@@ -1190,30 +1209,13 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
        aggstate->pergroup = pergroup;
    }
 
-   /*
-    * 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 9d0e5642229c08b861aff3d0d2f0e0dd3f0cbba4..bcb50fb7979917e0baa79f838cb2082b1835a3d0 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 97da70b2b7860fd3f0d890529275ef7cf4f7fb6e..f6df416d0f9faeb88c838869c6e0c1fb72a24e35 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 d41bcbb6fcc4091c02c41c0814f576564afc2c3f..3d562a476b8311e6548399276c3307e5c49e0d4a 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 c2c3ab66644af41e00d74c3479579edc82352988..9448ee466a87e1b52df9985f168db8e8938a1822 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 8f0e700ac35bfe345cd61c3a239bc56a8e381dc7..06796c590e3a67ea9880300f02fd873187cf5b5d 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,47 +296,60 @@ 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;
    Hash       *hashNode;
    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 78f5ad0ba26da6d8cee9192519d09528899c7af3..e9888c4d3f533db8313ef4fe36b7870687835377 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 4b22b93d579ca1f47cf4235f27f77801580e6a37..1ea3aa62b526fb4d53709ccf46d42b99bfaee112 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 30eb9a285b642d75c9be23ac41574465569a977a..cf7ca89f4a94910d889e25e7ccb3dbb601cdb04b 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 4237618b0e5f3cb42a3ef5adfb0ebc033992bb00..171738dd34917876e3a8afd31787746b4a87a50d 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 2bd26938fcc5d63fb200f09b5b91092827e18529..ae2061aa969e60b6ba1c32ce91a911df956fc593 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 d9d1608a81df740239236338c07012b19e8f1c43..f14fd01c424d047317ed41e92ae8d59d88e6a294 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 b6848d6c4b3aa2360d071b6ab96273ad30e020ef..e19098fba233973e2ae4e8644c52bd13eb4c105f 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,34 +252,34 @@ 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
     */
    heap_endscan(scanDesc);
 
+   /*
+    * clean out the tuple table
+    */
+   ExecClearTuple(node->ps.ps_ResultTupleSlot);
+   ExecClearTuple(node->ss_ScanTupleSlot);
+
    /*
     * close the heap relation.
     *
@@ -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 3d1cf2c8efa1ad73e58400aef2c79ff38ab4c3e3..a81a4a29d9117e714e278e6c6b8ba8f3133f36a0 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 05f36427beb75e9d7a9b83a6865e11b90353548c..e1b4db7a51d5922e89f33c2daeb6859f0e90f73c 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 73ff6370fbcd99a935124ad07540d392351e0605..195634c128982bc0b19c3704ebe8669060bbdc44 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 982dd0236ca32b0b26e7525360307497a023b2d1..ba0ed8635b72580e5a7c735f5e9241103e383bc5 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 0fb7c6df4a86b640f1e2a773929106eec123160d..53b3c26d35a18c5440f66127115247fb244a3f58 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 b71403de0b8f567e2a71817cfe3e42d3f062f418..88b08061f99803e3b2cebfb57ba217ae0226cf81 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 6e897e423eb569adcc06bd5e9398701ac07fa334..147becf6ed86eec9e89d4f9371c2b928df9bb8f0 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],
                                ¶mTypLen, ¶mTypByVal);
-               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 d11b5ed201f7b08e0b3864c4f2c1e76711abd1bd..1fe7efd16368f971c310d6d3d0422ade549ecfbd 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,313 +893,11 @@ _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
  */
@@ -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 c5a492db89c0861d29e0d8d09001187f45254598..f2cae4c14f4d2c9706a4f7f414ac1a6ca2b4cab1 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"
@@ -369,147 +369,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
  * Stuff from relation.h
  */
 
-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)
 {
@@ -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 3a074339f453d0de208a6501c744e0864428bf7a..2c254001eec926522737828c579f710819e17ee2 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 
 
 #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 148bd86b85a4a30985dcd36172e339d918bd422f..0414fdf2f3f1ced062251f73330294a75f75a79c 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 3db73e87f0bf00555b7b3b929be76172098ebf0e..b23843a030cdcb7556d2f992ba2a9e17dc40cb17 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.
  *
@@ -81,12 +80,6 @@ set_plan_references(Plan *plan, List *rtable)
    if (plan == NULL)
        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
     */
@@ -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 e4bbd29105ece5d2ab4196eafc6dfa55583cba45..a65de72c90b89c0f198df27c0dcff685dc23ce8e 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 84896b939fd84730023a97bdd474544517f1bf28..615d9966973a984ae0125eaf48a670bc24a79788 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 0919b03f45a9a4e10ddfd7bbc93eae7013c7be46..24d4aac8b2cbd348414cf069271b7f249a852bc1 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 4805c4481c5fb879fc983ed9be292e957880c9d3..eaead7dffc95fe0e54d2ad41985b1efe6830381b 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 363dabe43b4b7f38d8c49a7030bd5c15094501b7..9a95551d7c86d1ebfa9a67ea4faf48a0637ec98f 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 33b83bce6fe29caff2966ee7e80f5f8b7d381967..df3e52d4f0fcacb01689f652d7cf97d3947ffe3f 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 c912d3c9c093b7182ee81ea3854dbb6d46c7e3fd..036d67ccaadf0ba9ef6f5bd8c0f419797204cef2 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 4e9255b795dbd982bbf65945d7571a6540030dcf..3d18b66d1647fa81a3e34bfd3a386f6dec20116b 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 9a59cd217a42230defad761eb821b01ed7926f10..893d6b097efc61b4f7034c9a49066edc39ffff46 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 b3c4e5bbd051b045dc479bcf409a9e1449040a4a..211e55b6cadfe3a0bb80aef808a0b9a14a5aab6b 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 654906cd3c27140b635b80fe91813f2b11fad39a..c30073ec8cfe49e91858c336594201d50602f070 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 d13a8c9b05b13eb2cea9f86795fdb26021cf5268..9233c0758a4473e892051fcdae5cd469fc1cb53b 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 26596e5fdd46ac5e1b03ce58205849dd7378c25d..392807cce056ac7099597e5aa921d77793a8dc5c 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 16fa6072bee244c726ffa272b214a97c00938ee7..5b50335ee42f675052280295fef4f42c027f41cb 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 818fe7590ae730e71447b706c6b388e1c0cc5f04..8235bc82c83e78321045ab32c7a8771e84388def 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 b7ed7cd75b427ff2b1a10906ffed1ae31b59e085..1187d6bce2909e7171012f7c68a6e26a17f1759a 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 e6224753edc9cd29d15885c4fef8b9ff202d8c90..fd48820bbd9c021441036a078f2755a598df552f 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 5d90cda001dcce2ccb4e21a08ba5f87a7a5fc3ee..8a446408309aadd33c14f13537d180d7e8c38b8d 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 86d591c88c97f7a9b75915d88d1c448b9abdb8c6..683c4ab7dc9efae916c56c95f5baedc85b213c72 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 eb1b8c2518939f2959636b1d3007fd92b218ab2c..73b1e7f5fc55d5d402e2d10a1cea78c36c5f983a 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 ca2d1d5fb8a7ac7dda9b86d4a1222f06f1dc20cd..7836b32ab5b4dc7198038d19c5a05bbc5674f650 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 a061a420258156f8a6780299e8baeda53f6d334f..c573cf900dfc6561040fb16c6b51ed427d7e6a16 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 e1a5f01aaf29ced03e419d96ad97044c903841c8..5c5d5c8843975e146ac74fbef588fe5fc5c6052c 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 72e6c3e78f20db80aed967e3ab0f6bf7016be581..9aadb592ca1809953d7b85f5650b91655ed1ada5 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 f829b65338999f6ab9a8bb9ea6f44e49ba185d5a..d71997e531c1beed66a1a6ed2abf05ba481d1e4f 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 544510746d653649e35e8206bde5a97286948c5e..a4f10ef4c06e223cd2a1ccf6c84ef6fa346a0168 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,12 +746,22 @@ 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
  *
@@ -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 a9cd095f94e66329089c638fd0300a6c50b81ff8..cb16a300442b410464649de50f1abfa82024c9f4 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,
@@ -90,48 +131,16 @@ typedef enum NodeTag
    T_JoinInfo,
    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 ef0e0682be685d9907a2a353a72be367bc765f17..8f2eff5165efdb831bc6e3b154d92be041a783a3 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 6a6ac415f9f79b3c05840803c391c9b4215f53d6..097f8d93b1334bcb117ece115e0f358b172fb058 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,9 +330,18 @@ 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 7ebcef4f10fee7f1af2bcd04b3b2cb9cb4a9bc9b..07accf78f37b77fa5f06d22cdc942e4523d605a3 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 5f6ad686dff212878db20b9604e0d79bf360a33e..333ca0b695b497572943cccdc2e8cc3c14237273 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 a29b1857ec6a8c9c4e8b7ef6367da8e6080e9791..b00142499777b306b50b5802e74cc038ce8273e3 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 ba784fee03a5be3dc2c6416571916d50fef1192e..40258acc32a34113804457127bb9b0f2339ff9af 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 2bdf24116c9b07489036535106cc20fa59ad8385..007a3ffbe7955060583d5d9d3c3a6f9a89b58dfd 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;