OSDN Git Service

Clean up plantree representation of SubPlan-s --- SubLink does not appear
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 Dec 2002 00:17:59 +0000 (00:17 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 Dec 2002 00:17:59 +0000 (00:17 +0000)
in the planned representation of a subplan at all any more, only SubPlan.
This means subselect.c doesn't scribble on its input anymore, which seems
like a good thing; and there are no longer three different possible
interpretations of a SubLink.  Simplify node naming and improve comments
in primnodes.h.  No change to stored rules, though.

24 files changed:
src/backend/commands/explain.c
src/backend/executor/execAmi.c
src/backend/executor/execProcnode.c
src/backend/executor/execQual.c
src/backend/executor/nodeSubplan.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/var.c
src/backend/utils/adt/ruleutils.c
src/include/executor/executor.h
src/include/executor/nodeSubplan.h
src/include/nodes/execnodes.h
src/include/nodes/nodes.h
src/include/nodes/params.h
src/include/nodes/primnodes.h
src/include/optimizer/clauses.h

index 1f9e754..05815a2 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.97 2002/12/13 19:45:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.98 2002/12/14 00:17:50 tgl Exp $
  *
  */
 
@@ -589,8 +589,8 @@ explain_outNode(StringInfo str,
                appendStringInfo(str, "  InitPlan\n");
                foreach(lst, planstate->initPlan)
                {
-                       SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
-                       SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
+                       SubPlanState *sps = (SubPlanState *) lfirst(lst);
+                       SubPlan *sp = (SubPlan *) sps->xprstate.expr;
 
                        es->rtable = sp->rtable;
                        for (i = 0; i < indent; i++)
@@ -687,8 +687,8 @@ explain_outNode(StringInfo str,
                appendStringInfo(str, "  SubPlan\n");
                foreach(lst, planstate->subPlan)
                {
-                       SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
-                       SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
+                       SubPlanState *sps = (SubPlanState *) lfirst(lst);
+                       SubPlan *sp = (SubPlan *) sps->xprstate.expr;
 
                        es->rtable = sp->rtable;
                        for (i = 0; i < indent; i++)
index fa95ad6..c55e5ec 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
  *
- *     $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.67 2002/12/13 19:45:52 tgl Exp $
+ *     $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.68 2002/12/14 00:17:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,7 +61,7 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
 
                foreach(lst, node->initPlan)
                {
-                       SubPlanExprState  *sstate = (SubPlanExprState *) lfirst(lst);
+                       SubPlanState  *sstate = (SubPlanState *) lfirst(lst);
                        PlanState  *splan = sstate->planstate;
 
                        if (splan->plan->extParam != NIL)       /* don't care about child
@@ -72,7 +72,7 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
                }
                foreach(lst, node->subPlan)
                {
-                       SubPlanExprState  *sstate = (SubPlanExprState *) lfirst(lst);
+                       SubPlanState  *sstate = (SubPlanState *) lfirst(lst);
                        PlanState  *splan = sstate->planstate;
 
                        if (splan->plan->extParam != NIL)
index 59c798b..dc5a308 100644 (file)
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.33 2002/12/13 19:45:52 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.34 2002/12/14 00:17:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -228,10 +228,10 @@ ExecInitNode(Plan *node, EState *estate)
        subps = NIL;
        foreach(subp, node->initPlan)
        {
-               SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
-               SubPlanExprState *sstate;
+               SubPlan    *subplan = (SubPlan *) lfirst(subp);
+               SubPlanState *sstate;
 
-               Assert(IsA(subplan, SubPlanExpr));
+               Assert(IsA(subplan, SubPlan));
                sstate = ExecInitExprInitPlan(subplan, result);
                ExecInitSubPlan(sstate, estate);
                subps = lappend(subps, sstate);
@@ -247,9 +247,9 @@ ExecInitNode(Plan *node, EState *estate)
        subps = NIL;
        foreach(subp, result->subPlan)
        {
-               SubPlanExprState *sstate = (SubPlanExprState *) lfirst(subp);
+               SubPlanState *sstate = (SubPlanState *) lfirst(subp);
 
-               Assert(IsA(sstate, SubPlanExprState));
+               Assert(IsA(sstate, SubPlanState));
                ExecInitSubPlan(sstate, estate);
                subps = lappend(subps, sstate);
        }
@@ -500,9 +500,9 @@ ExecEndNode(PlanState *node)
 
        /* Clean up initPlans and subPlans */
        foreach(subp, node->initPlan)
-               ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
+               ExecEndSubPlan((SubPlanState *) lfirst(subp));
        foreach(subp, node->subPlan)
-               ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
+               ExecEndSubPlan((SubPlanState *) lfirst(subp));
 
        if (node->chgParam != NIL)
        {
index b529d04..a3f79c3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.119 2002/12/13 19:45:52 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.120 2002/12/14 00:17:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1794,8 +1794,8 @@ ExecEvalExpr(ExprState *expression,
                                }
                                break;
                        }
-               case T_SubPlanExpr:
-                       retDatum = ExecSubPlan((SubPlanExprState *) expression,
+               case T_SubPlan:
+                       retDatum = ExecSubPlan((SubPlanState *) expression,
                                                                   econtext,
                                                                   isNull);
                        break;
@@ -1883,7 +1883,7 @@ ExecEvalExprSwitchContext(ExprState *expression,
  * executions of the expression are needed.  Typically the context will be
  * the same as the per-query context of the associated ExprContext.
  *
- * Any Aggref and SubplanExpr nodes found in the tree are added to the lists
+ * Any Aggref and SubPlan nodes found in the tree are added to the lists
  * of such nodes held by the parent PlanState.  Otherwise, we do very little
  * initialization here other than building the state-node tree.  Any nontrivial
  * work associated with initializing runtime info for a node should happen
@@ -2003,31 +2003,26 @@ ExecInitExpr(Expr *node, PlanState *parent)
                                state = (ExprState *) bstate;
                        }
                        break;
-               case T_SubPlanExpr:
+               case T_SubPlan:
                        {
                                /* Keep this in sync with ExecInitExprInitPlan, below */
-                               SubPlanExpr *subplanexpr = (SubPlanExpr *) node;
-                               SubLink *sublink = subplanexpr->sublink;
-                               SubPlanExprState *sstate = makeNode(SubPlanExprState);
+                               SubPlan *subplan = (SubPlan *) node;
+                               SubPlanState *sstate = makeNode(SubPlanState);
 
-                               Assert(IsA(sublink, SubLink));
                                if (!parent)
-                                       elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
+                                       elog(ERROR, "ExecInitExpr: SubPlan not expected here");
 
                                /*
-                                * Here we just add the SubPlanExprState nodes to
+                                * Here we just add the SubPlanState nodes to
                                 * parent->subPlan.  The subplans will be initialized later.
                                 */
                                parent->subPlan = lcons(sstate, parent->subPlan);
                                sstate->planstate = NULL;
 
-                               sstate->args = (List *)
-                                       ExecInitExpr((Expr *) subplanexpr->args, parent);
-
-                               if (sublink->lefthand)
-                                       elog(ERROR, "ExecInitExpr: sublink has not been transformed");
                                sstate->oper = (List *)
-                                       ExecInitExpr((Expr *) sublink->oper, parent);
+                                       ExecInitExpr((Expr *) subplan->oper, parent);
+                               sstate->args = (List *)
+                                       ExecInitExpr((Expr *) subplan->args, parent);
 
                                state = (ExprState *) sstate;
                        }
@@ -2145,26 +2140,20 @@ ExecInitExpr(Expr *node, PlanState *parent)
  * subplan expr, except we do NOT want to add the node to the parent's
  * subplan list.
  */
-SubPlanExprState *
-ExecInitExprInitPlan(SubPlanExpr *node, PlanState *parent)
+SubPlanState *
+ExecInitExprInitPlan(SubPlan *node, PlanState *parent)
 {
-       SubLink *sublink = node->sublink;
-       SubPlanExprState *sstate = makeNode(SubPlanExprState);
+       SubPlanState *sstate = makeNode(SubPlanState);
 
-       Assert(IsA(sublink, SubLink));
        if (!parent)
-               elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
+               elog(ERROR, "ExecInitExpr: SubPlan not expected here");
 
        /* The subplan's state will be initialized later */
        sstate->planstate = NULL;
 
+       sstate->oper = (List *) ExecInitExpr((Expr *) node->oper, parent);
        sstate->args = (List *) ExecInitExpr((Expr *) node->args, parent);
 
-       if (sublink->lefthand)
-               elog(ERROR, "ExecInitExpr: sublink has not been transformed");
-
-       sstate->oper = (List *) ExecInitExpr((Expr *) sublink->oper, parent);
-
        sstate->xprstate.expr = (Expr *) node;
 
        return sstate;
index 69fcc58..3a2ca97 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.37 2002/12/13 19:45:55 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.38 2002/12/14 00:17:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * ----------------------------------------------------------------
  */
 Datum
-ExecSubPlan(SubPlanExprState *node,
+ExecSubPlan(SubPlanState *node,
                        ExprContext *econtext,
                        bool *isNull)
 {
+       SubPlan    *subplan = (SubPlan *) node->xprstate.expr;
        PlanState  *planstate = node->planstate;
-       SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
-       SubLink    *sublink = subplan->sublink;
-       SubLinkType subLinkType = sublink->subLinkType;
-       bool            useor = sublink->useor;
+       SubLinkType subLinkType = subplan->subLinkType;
+       bool            useor = subplan->useor;
        MemoryContext oldcontext;
        TupleTableSlot *slot;
        Datum           result;
@@ -292,56 +291,56 @@ ExecSubPlan(SubPlanExprState *node,
  * ----------------------------------------------------------------
  */
 void
-ExecInitSubPlan(SubPlanExprState *sstate, EState *estate)
+ExecInitSubPlan(SubPlanState *node, EState *estate)
 {
-       SubPlanExpr *expr = (SubPlanExpr *) sstate->xprstate.expr;
+       SubPlan    *subplan = (SubPlan *) node->xprstate.expr;
        EState     *sp_estate;
 
        /*
         * Do access checking on the rangetable entries in the subquery.
         * Here, we assume the subquery is a SELECT.
         */
-       ExecCheckRTPerms(expr->rtable, CMD_SELECT);
+       ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
 
        /*
         * initialize state
         */
-       sstate->needShutdown = false;
-       sstate->curTuple = NULL;
+       node->needShutdown = false;
+       node->curTuple = NULL;
 
        /*
         * create an EState for the subplan
         */
        sp_estate = CreateExecutorState();
 
-       sp_estate->es_range_table = expr->rtable;
+       sp_estate->es_range_table = subplan->rtable;
        sp_estate->es_param_list_info = estate->es_param_list_info;
        sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
        sp_estate->es_tupleTable =
-               ExecCreateTupleTable(ExecCountSlotsNode(expr->plan) + 10);
+               ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);
        sp_estate->es_snapshot = estate->es_snapshot;
        sp_estate->es_instrument = estate->es_instrument;
 
        /*
         * Start up the subplan
         */
-       sstate->planstate = ExecInitNode(expr->plan, sp_estate);
+       node->planstate = ExecInitNode(subplan->plan, sp_estate);
 
-       sstate->needShutdown = true;    /* now we need to shutdown the subplan */
+       node->needShutdown = true;      /* now we need to shutdown the subplan */
 
        /*
         * If this plan is un-correlated or undirect correlated one and want
         * to set params for parent plan then prepare parameters.
         */
-       if (expr->setParam != NIL)
+       if (subplan->setParam != NIL)
        {
                List       *lst;
 
-               foreach(lst, expr->setParam)
+               foreach(lst, subplan->setParam)
                {
                        ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
 
-                       prm->execPlan = sstate;
+                       prm->execPlan = node;
                }
 
                /*
@@ -366,11 +365,11 @@ ExecInitSubPlan(SubPlanExprState *sstate, EState *estate)
  * ----------------------------------------------------------------
  */
 void
-ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext)
+ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 {
+       SubPlan    *subplan = (SubPlan *) node->xprstate.expr;
        PlanState  *planstate = node->planstate;
-       SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
-       SubLinkType     subLinkType = subplan->sublink->subLinkType;
+       SubLinkType     subLinkType = subplan->subLinkType;
        MemoryContext oldcontext;
        TupleTableSlot *slot;
        List       *lst;
@@ -473,7 +472,7 @@ ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext)
  * ----------------------------------------------------------------
  */
 void
-ExecEndSubPlan(SubPlanExprState *node)
+ExecEndSubPlan(SubPlanState *node)
 {
        if (node->needShutdown)
        {
@@ -488,10 +487,10 @@ ExecEndSubPlan(SubPlanExprState *node)
 }
 
 void
-ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent)
+ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
 {
        PlanState  *planstate = node->planstate;
-       SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
+       SubPlan    *subplan = (SubPlan *) node->xprstate.expr;
        EState     *estate = parent->state;
        List       *lst;
 
index d84e606..c3abcfc 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.232 2002/12/13 19:45:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.233 2002/12/14 00:17:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -818,21 +818,22 @@ _copySubLink(SubLink *from)
 }
 
 /*
- * _copySubPlanExpr
+ * _copySubPlan
  */
-static SubPlanExpr *
-_copySubPlanExpr(SubPlanExpr *from)
+static SubPlan *
+_copySubPlan(SubPlan *from)
 {
-       SubPlanExpr    *newnode = makeNode(SubPlanExpr);
+       SubPlan    *newnode = makeNode(SubPlan);
 
-       COPY_SCALAR_FIELD(typeOid);
+       COPY_SCALAR_FIELD(subLinkType);
+       COPY_SCALAR_FIELD(useor);
+       COPY_NODE_FIELD(oper);
        COPY_NODE_FIELD(plan);
        COPY_SCALAR_FIELD(plan_id);
        COPY_NODE_FIELD(rtable);
        COPY_INTLIST_FIELD(setParam);
        COPY_INTLIST_FIELD(parParam);
        COPY_NODE_FIELD(args);
-       COPY_NODE_FIELD(sublink);
 
        return newnode;
 }
@@ -2431,8 +2432,8 @@ copyObject(void *from)
                case T_SubLink:
                        retval = _copySubLink(from);
                        break;
-               case T_SubPlanExpr:
-                       retval = _copySubPlanExpr(from);
+               case T_SubPlan:
+                       retval = _copySubPlan(from);
                        break;
                case T_FieldSelect:
                        retval = _copyFieldSelect(from);
index 3fc9240..5fc333d 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.176 2002/12/12 20:35:12 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.177 2002/12/14 00:17:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -296,16 +296,17 @@ _equalSubLink(SubLink *a, SubLink *b)
 }
 
 static bool
-_equalSubPlanExpr(SubPlanExpr *a, SubPlanExpr *b)
+_equalSubPlan(SubPlan *a, SubPlan *b)
 {
-       COMPARE_SCALAR_FIELD(typeOid);
+       COMPARE_SCALAR_FIELD(subLinkType);
+       COMPARE_SCALAR_FIELD(useor);
+       COMPARE_NODE_FIELD(oper);
        /* should compare plans, but have to settle for comparing plan IDs */
        COMPARE_SCALAR_FIELD(plan_id);
        COMPARE_NODE_FIELD(rtable);
        COMPARE_INTLIST_FIELD(setParam);
        COMPARE_INTLIST_FIELD(parParam);
        COMPARE_NODE_FIELD(args);
-       COMPARE_NODE_FIELD(sublink);
 
        return true;
 }
@@ -1561,8 +1562,8 @@ equal(void *a, void *b)
                case T_SubLink:
                        retval = _equalSubLink(a, b);
                        break;
-               case T_SubPlanExpr:
-                       retval = _equalSubPlanExpr(a, b);
+               case T_SubPlan:
+                       retval = _equalSubPlan(a, b);
                        break;
                case T_FieldSelect:
                        retval = _equalFieldSelect(a, b);
index a688b47..97fc946 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.189 2002/12/13 19:45:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.190 2002/12/14 00:17:52 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -665,18 +665,19 @@ _outSubLink(StringInfo str, SubLink *node)
 }
 
 static void
-_outSubPlanExpr(StringInfo str, SubPlanExpr *node)
+_outSubPlan(StringInfo str, SubPlan *node)
 {
-       WRITE_NODE_TYPE("SUBPLANEXPR");
+       WRITE_NODE_TYPE("SUBPLAN");
 
-       WRITE_OID_FIELD(typeOid);
+       WRITE_ENUM_FIELD(subLinkType, SubLinkType);
+       WRITE_BOOL_FIELD(useor);
+       WRITE_NODE_FIELD(oper);
        WRITE_NODE_FIELD(plan);
        WRITE_INT_FIELD(plan_id);
        WRITE_NODE_FIELD(rtable);
        WRITE_INTLIST_FIELD(setParam);
        WRITE_INTLIST_FIELD(parParam);
        WRITE_NODE_FIELD(args);
-       WRITE_NODE_FIELD(sublink);
 }
 
 static void
@@ -1498,8 +1499,8 @@ _outNode(StringInfo str, void *obj)
                        case T_SubLink:
                                _outSubLink(str, obj);
                                break;
-                       case T_SubPlanExpr:
-                               _outSubPlanExpr(str, obj);
+                       case T_SubPlan:
+                               _outSubPlan(str, obj);
                                break;
                        case T_FieldSelect:
                                _outFieldSelect(str, obj);
index 54e3916..9ecd40f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.143 2002/12/13 19:45:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.144 2002/12/14 00:17:54 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -540,7 +540,7 @@ _readSubLink(void)
 }
 
 /*
- * _readSubPlanExpr is not needed since it doesn't appear in stored rules.
+ * _readSubPlan is not needed since it doesn't appear in stored rules.
  */
 
 /*
index 114e879..5feaed4 100644 (file)
@@ -42,7 +42,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.95 2002/12/13 17:29:25 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.96 2002/12/14 00:17:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1234,7 +1234,7 @@ cost_qual_eval_walker(Node *node, Cost *total)
                IsA(node, OpExpr) ||
                IsA(node, DistinctExpr))
                *total += cpu_operator_cost;
-       else if (IsA(node, SubPlanExpr))
+       else if (IsA(node, SubPlan))
        {
                /*
                 * A subplan node in an expression indicates that the
@@ -1246,18 +1246,18 @@ cost_qual_eval_walker(Node *node, Cost *total)
                 * NOTE: this logic should agree with the estimates used by
                 * make_subplan() in plan/subselect.c.
                 */
-               SubPlanExpr *subplan = (SubPlanExpr *) node;
+               SubPlan    *subplan = (SubPlan *) node;
                Plan       *plan = subplan->plan;
                Cost            subcost;
 
-               if (subplan->sublink->subLinkType == EXISTS_SUBLINK)
+               if (subplan->subLinkType == EXISTS_SUBLINK)
                {
                        /* we only need to fetch 1 tuple */
                        subcost = plan->startup_cost +
                                (plan->total_cost - plan->startup_cost) / plan->plan_rows;
                }
-               else if (subplan->sublink->subLinkType == ALL_SUBLINK ||
-                                subplan->sublink->subLinkType == ANY_SUBLINK)
+               else if (subplan->subLinkType == ALL_SUBLINK ||
+                                subplan->subLinkType == ANY_SUBLINK)
                {
                        /* assume we need 50% of the tuples */
                        subcost = plan->startup_cost +
index b3d7b53..b7c0c2a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.134 2002/12/12 15:49:32 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.135 2002/12/14 00:17:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -91,7 +91,7 @@ planner(Query *parse)
         * purpose is communication across multiple sub-Queries.
         *
         * Note we do NOT save and restore PlannerPlanId: it exists to assign
-        * unique IDs to SubPlanExpr nodes, and we want those IDs to be unique for
+        * unique IDs to SubPlan nodes, and we want those IDs to be unique for
         * the life of a backend.  Also, PlannerInitPlan is saved/restored in
         * subquery_planner, not here.
         */
@@ -278,7 +278,7 @@ subquery_planner(Query *parse, double tuple_fraction)
                /* Must add the initPlans' extParams to the topmost node's, too */
                foreach(lst, plan->initPlan)
                {
-                       SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
+                       SubPlan    *subplan = (SubPlan *) lfirst(lst);
 
                        plan->extParam = set_unioni(plan->extParam,
                                                                                subplan->plan->extParam);
index 0d66c97..5081f9c 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.85 2002/12/12 15:49:32 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.86 2002/12/14 00:17:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -219,7 +219,7 @@ set_plan_references(Plan *plan, List *rtable)
         * 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
-        * children.  Fortunately, that consideration doesn't apply to SubPlanExpr
+        * 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);
@@ -227,9 +227,9 @@ set_plan_references(Plan *plan, List *rtable)
 
        foreach(pl, plan->initPlan)
        {
-               SubPlanExpr *sp = (SubPlanExpr *) lfirst(pl);
+               SubPlan *sp = (SubPlan *) lfirst(pl);
 
-               Assert(IsA(sp, SubPlanExpr));
+               Assert(IsA(sp, SubPlan));
                set_plan_references(sp->plan, sp->rtable);
        }
 }
@@ -259,9 +259,9 @@ fix_expr_references_walker(Node *node, void *context)
                set_opfuncid((OpExpr *) node);
        else if (IsA(node, DistinctExpr))
                set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
-       else if (IsA(node, SubPlanExpr))
+       else if (IsA(node, SubPlan))
        {
-               SubPlanExpr *sp = (SubPlanExpr *) node;
+               SubPlan *sp = (SubPlan *) node;
 
                set_plan_references(sp->plan, sp->rtable);
        }
index fe17b8e..840ba97 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.60 2002/12/12 15:49:32 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.61 2002/12/14 00:17:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,8 +53,17 @@ int                  PlannerPlanId = 0;      /* to assign unique ID to subquery plans */
  */
 
 
-static void convert_sublink_opers(SubLink *slink, List *targetlist,
-                                                                 List **setParams);
+typedef struct finalize_primnode_results
+{
+       List       *paramids;           /* List of PARAM_EXEC paramids found */
+} finalize_primnode_results;
+
+
+static List *convert_sublink_opers(List *operlist, List *lefthand,
+                                                                  List *targetlist, List **setParams);
+static Node *replace_correlation_vars_mutator(Node *node, void *context);
+static Node *process_sublinks_mutator(Node *node, void *context);
+static bool finalize_primnode(Node *node, finalize_primnode_results *results);
 
 
 /*
@@ -144,30 +153,28 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
 }
 
 /*
- * Convert a bare SubLink (as created by the parser) into a SubPlanExpr.
+ * Convert a bare SubLink (as created by the parser) into a SubPlan.
+ *
+ * We are given the raw SubLink and the already-processed lefthand argument
+ * list (use this instead of the SubLink's own field).
+ *
+ * The result is whatever we need to substitute in place of the SubLink
+ * node in the executable expression.  This will be either the SubPlan
+ * node (if we have to do the subplan as a subplan), or a Param node
+ * representing the result of an InitPlan, or possibly an AND or OR tree
+ * containing InitPlan Param nodes.
  */
 static Node *
-make_subplan(SubLink *slink)
+make_subplan(SubLink *slink, List *lefthand)
 {
-       SubPlanExpr *node = makeNode(SubPlanExpr);
+       SubPlan    *node = makeNode(SubPlan);
        Query      *subquery = (Query *) (slink->subselect);
-       Oid                     result_type = exprType((Node *) slink);
        double          tuple_fraction;
        Plan       *plan;
        List       *lst;
        Node       *result;
 
        /*
-        * Check to see if this node was already processed; if so we have
-        * trouble.  We check to see if the linked-to Query appears to have
-        * been planned already, too.
-        */
-       if (subquery == NULL)
-               elog(ERROR, "make_subplan: invalid expression structure (SubLink already processed?)");
-       if (subquery->base_rel_list != NIL)
-               elog(ERROR, "make_subplan: invalid expression structure (subquery already processed?)");
-
-       /*
         * Copy the source Query node.  This is a quick and dirty kluge to
         * resolve the fact that the parser can generate trees with multiple
         * links to the same sub-Query node, but the planner wants to scribble
@@ -210,14 +217,19 @@ make_subplan(SubLink *slink)
        node->plan = plan = subquery_planner(subquery, tuple_fraction);
 
        node->plan_id = PlannerPlanId++;        /* Assign unique ID to this
-                                                                                * SubPlanExpr */
+                                                                                * SubPlan */
 
        node->rtable = subquery->rtable;
-       node->sublink = slink;
-
-       node->typeOid = result_type;
 
-       slink->subselect = NULL;        /* cool ?! see error check above! */
+       /*
+        * Fill in other fields of the SubPlan node.
+        */
+       node->subLinkType = slink->subLinkType;
+       node->useor = slink->useor;
+       node->oper = NIL;
+       node->setParam = NIL;
+       node->parParam = NIL;
+       node->args = NIL;
 
        /*
         * Make parParam list of params that current query level will pass to
@@ -262,17 +274,23 @@ make_subplan(SubLink *slink)
        }
        else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
        {
-               convert_sublink_opers(slink, plan->targetlist, &node->setParam);
+               List   *oper;
+
+               /* Convert the oper list, but don't put it into the SubPlan node */
+               oper = convert_sublink_opers(slink->oper,
+                                                                        lefthand,
+                                                                        plan->targetlist,
+                                                                        &node->setParam);
                PlannerInitPlan = lappend(PlannerInitPlan, node);
-               if (length(slink->oper) > 1)
-                       result = (Node *) ((slink->useor) ? make_orclause(slink->oper) :
-                                                          make_andclause(slink->oper));
+               if (length(oper) > 1)
+                       result = (Node *) (node->useor ? make_orclause(oper) :
+                                                          make_andclause(oper));
                else
-                       result = (Node *) lfirst(slink->oper);
+                       result = (Node *) lfirst(oper);
        }
        else
        {
-               List       *args = NIL;
+               List       *args;
 
                /*
                 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
@@ -347,12 +365,16 @@ make_subplan(SubLink *slink)
                        }
                }
 
-               /* Fix the SubLink's oper list */
-               convert_sublink_opers(slink, plan->targetlist, NULL);
+               /* Convert the SubLink's oper list into executable form */
+               node->oper = convert_sublink_opers(slink->oper,
+                                                                                  lefthand,
+                                                                                  plan->targetlist,
+                                                                                  NULL);
 
                /*
                 * Make node->args from parParam.
                 */
+               args = NIL;
                foreach(lst, node->parParam)
                {
                        Var                *var = nth(lfirsti(lst), PlannerParamVar);
@@ -379,27 +401,26 @@ make_subplan(SubLink *slink)
  * convert_sublink_opers: convert a SubLink's oper list from the
  * parser/rewriter format into the executor's format.
  *
- * The oper list is initially just a list of OpExpr nodes.  We replace it
- * with a list of actually executable expressions, in which the specified
- * operators are applied to corresponding elements of the lefthand list
- * and Params representing the results of the subplan.  lefthand is then
- * set to NIL.
+ * The oper list is initially a list of OpExpr nodes with NIL args.  We
+ * convert it to a list of actually executable expressions, in which the
+ * specified operators are applied to corresponding elements of the
+ * lefthand list and Params representing the results of the subplan.
  *
  * If setParams is not NULL, the paramids of the Params created are added
  * to the *setParams list.
  */
-static void
-convert_sublink_opers(SubLink *slink, List *targetlist,
-                                         List **setParams)
+static List *
+convert_sublink_opers(List *operlist, List *lefthand,
+                                         List *targetlist, List **setParams)
 {
        List       *newoper = NIL;
-       List       *leftlist = slink->lefthand;
+       List       *leftlist = lefthand;
        List       *lst;
 
-       foreach(lst, slink->oper)
+       foreach(lst, operlist)
        {
                OpExpr     *oper = (OpExpr *) lfirst(lst);
-               Node       *lefthand = lfirst(leftlist);
+               Node       *leftop = lfirst(leftlist);
                TargetEntry *te = lfirst(targetlist);
                Param      *prm;
                Operator        tup;
@@ -430,7 +451,7 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
                 * Note: we use make_operand in case runtime type conversion
                 * function calls must be inserted for this operator!
                 */
-               left = make_operand(lefthand, exprType(lefthand), opform->oprleft);
+               left = make_operand(leftop, exprType(leftop), opform->oprleft);
                right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
                newoper = lappend(newoper,
                                                  make_opclause(oper->opno,
@@ -445,65 +466,12 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
                targetlist = lnext(targetlist);
        }
 
-       slink->oper = newoper;
-       slink->lefthand = NIL;
-}
-
-/*
- * 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       *paramids;           /* List of PARAM_EXEC paramids found */
-} finalize_primnode_results;
-
-static bool
-finalize_primnode(Node *node, finalize_primnode_results *results)
-{
-       if (node == NULL)
-               return false;
-       if (IsA(node, Param))
-       {
-               if (((Param *) node)->paramkind == PARAM_EXEC)
-               {
-                       int                     paramid = (int) ((Param *) node)->paramid;
-
-                       if (!intMember(paramid, results->paramids))
-                               results->paramids = lconsi(paramid, results->paramids);
-               }
-               return false;                   /* no more to do here */
-       }
-       if (is_subplan(node))
-       {
-               SubPlanExpr *subplan = (SubPlanExpr *) node;
-               List       *lst;
-
-               /* Check extParam list for params to add to paramids */
-               foreach(lst, subplan->plan->extParam)
-               {
-                       int                     paramid = lfirsti(lst);
-                       Var                *var = nth(paramid, PlannerParamVar);
-
-                       /* note varlevelsup is absolute level number */
-                       if (var->varlevelsup < PlannerQueryLevel &&
-                               !intMember(paramid, results->paramids))
-                               results->paramids = lconsi(paramid, results->paramids);
-               }
-               /* fall through to recurse into subplan args */
-       }
-       return expression_tree_walker(node, finalize_primnode,
-                                                                 (void *) results);
+       return newoper;
 }
 
 /*
  * Replace correlation vars (uplevel vars) with Params.
  */
-
-static Node *replace_correlation_vars_mutator(Node *node, void *context);
-
 Node *
 SS_replace_correlation_vars(Node *expr)
 {
@@ -529,9 +497,6 @@ replace_correlation_vars_mutator(Node *node, void *context)
 /*
  * Expand SubLinks to SubPlans in the given expression.
  */
-
-static Node *process_sublinks_mutator(Node *node, void *context);
-
 Node *
 SS_process_sublinks(Node *expr)
 {
@@ -547,20 +512,21 @@ process_sublinks_mutator(Node *node, void *context)
        if (IsA(node, SubLink))
        {
                SubLink    *sublink = (SubLink *) node;
+               List       *lefthand;
 
                /*
-                * First, scan the lefthand-side expressions, if any. This is a
-                * tad klugy since we modify the input SubLink node, but that
-                * should be OK (make_subplan does it too!)
+                * First, recursively process the lefthand-side expressions, if any.
                 */
-               sublink->lefthand = (List *)
+               lefthand = (List *)
                        process_sublinks_mutator((Node *) sublink->lefthand, context);
-               /* Now build the SubPlanExpr node and make the expr to return */
-               return make_subplan(sublink);
+               /*
+                * Now build the SubPlan node and make the expr to return.
+                */
+               return make_subplan(sublink, lefthand);
        }
 
        /*
-        * Note that we will never see a SubPlanExpr expression in the input
+        * Note that we will never see a SubPlan expression in the input
         * (since this is the very routine that creates 'em to begin with). So
         * the code in expression_tree_mutator() that might do inappropriate
         * things with SubPlans or SubLinks will not be exercised.
@@ -572,6 +538,12 @@ process_sublinks_mutator(Node *node, void *context)
                                                                   context);
 }
 
+/*
+ * SS_finalize_plan - do final sublink processing for a completed Plan.
+ *
+ * This recursively computes and sets the extParam and locParam lists
+ * for every Plan node in the given tree.
+ */
 List *
 SS_finalize_plan(Plan *plan, List *rtable)
 {
@@ -721,3 +693,46 @@ SS_finalize_plan(Plan *plan, List *rtable)
 
        return results.paramids;
 }
+
+/*
+ * 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!
+ */
+static bool
+finalize_primnode(Node *node, finalize_primnode_results *results)
+{
+       if (node == NULL)
+               return false;
+       if (IsA(node, Param))
+       {
+               if (((Param *) node)->paramkind == PARAM_EXEC)
+               {
+                       int                     paramid = (int) ((Param *) node)->paramid;
+
+                       if (!intMember(paramid, results->paramids))
+                               results->paramids = lconsi(paramid, results->paramids);
+               }
+               return false;                   /* no more to do here */
+       }
+       if (is_subplan(node))
+       {
+               SubPlan    *subplan = (SubPlan *) node;
+               List       *lst;
+
+               /* Check extParam list for params to add to paramids */
+               foreach(lst, subplan->plan->extParam)
+               {
+                       int                     paramid = lfirsti(lst);
+                       Var                *var = nth(paramid, PlannerParamVar);
+
+                       /* note varlevelsup is absolute level number */
+                       if (var->varlevelsup < PlannerQueryLevel &&
+                               !intMember(paramid, results->paramids))
+                               results->paramids = lconsi(paramid, results->paramids);
+               }
+               /* fall through to recurse into subplan args */
+       }
+       return expression_tree_walker(node, finalize_primnode,
+                                                                 (void *) results);
+}
index a55af2e..5e44a64 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.82 2002/12/12 15:49:32 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.83 2002/12/14 00:17:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -872,13 +872,13 @@ adjust_inherited_attrs_mutator(Node *node,
         */
        if (is_subplan(node))
        {
-               SubPlanExpr *subplan;
+               SubPlan *subplan;
 
                /* Copy the node and process subplan args */
                node = expression_tree_mutator(node, adjust_inherited_attrs_mutator,
                                                                           (void *) context);
                /* Make sure we have separate copies of subplan and its rtable */
-               subplan = (SubPlanExpr *) node;
+               subplan = (SubPlan *) node;
                subplan->plan = copyObject(subplan->plan);
                subplan->rtable = copyObject(subplan->rtable);
                return node;
index af96615..1d87afd 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.118 2002/12/13 19:45:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.119 2002/12/14 00:17:59 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -486,7 +486,7 @@ expression_returns_set_walker(Node *node, void *context)
                return false;
        if (IsA(node, SubLink))
                return false;
-       if (IsA(node, SubPlanExpr))
+       if (IsA(node, SubPlan))
                return false;
 
        return expression_tree_walker(node, expression_returns_set_walker,
@@ -519,7 +519,7 @@ contain_subplans_walker(Node *node, void *context)
 {
        if (node == NULL)
                return false;
-       if (IsA(node, SubPlanExpr) ||
+       if (IsA(node, SubPlan) ||
                IsA(node, SubLink))
                return true;                    /* abort the tree traversal and return
                                                                 * true */
@@ -530,7 +530,7 @@ contain_subplans_walker(Node *node, void *context)
  * pull_subplans
  *       Recursively pulls all subplans from an expression tree.
  *
- *       Returns list of SubPlanExpr nodes found.  Note the nodes themselves
+ *       Returns list of SubPlan nodes found.  Note the nodes themselves
  *       are not copied, only referenced.
  */
 List *
@@ -656,7 +656,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
                 */
                List       *t;
 
-               foreach(t, ((SubPlanExpr *) node)->args)
+               foreach(t, ((SubPlan *) node)->args)
                {
                        Node       *thisarg = lfirst(t);
                        Var                *var;
@@ -1483,14 +1483,14 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
                                break;
                }
        }
-       if (IsA(node, SubPlanExpr))
+       if (IsA(node, SubPlan))
        {
                /*
-                * Return a SubPlanExpr unchanged --- too late to do anything
+                * Return a SubPlan unchanged --- too late to do anything
                 * with it.
                 *
                 * XXX should we elog() here instead?  Probably this routine
-                * should never be invoked after SubPlanExpr creation.
+                * should never be invoked after SubPlan creation.
                 */
                return node;
        }
@@ -2089,17 +2089,17 @@ substitute_actual_parameters_mutator(Node *node,
  * FromExpr, JoinExpr, and SetOperationStmt nodes are handled, so that query
  * jointrees and setOperation trees can be processed without additional code.
  *
- * expression_tree_walker will handle SubLink and SubPlanExpr nodes by
- * recursing normally into the "lefthand" arguments (which are expressions
- * belonging to the outer plan).  It will also call the walker on the
- * sub-Query node; however, when expression_tree_walker itself is called on a
- * Query node, it does nothing and returns "false".  The net effect is that
- * unless the walker does something special at a Query node, sub-selects will
- * not be visited during an expression tree walk. This is exactly the behavior
- * wanted in many cases --- and for those walkers that do want to recurse into
- * sub-selects, special behavior is typically needed anyway at the entry to a
- * sub-select (such as incrementing a depth counter). A walker that wants to
- * examine sub-selects should include code along the lines of:
+ * expression_tree_walker will handle SubLink nodes by recursing normally into
+ * the "lefthand" arguments (which are expressions belonging to the outer
+ * plan).  It will also call the walker on the sub-Query node; however, when
+ * expression_tree_walker itself is called on a Query node, it does nothing
+ * and returns "false".  The net effect is that unless the walker does
+ * something special at a Query node, sub-selects will not be visited during
+ * an expression tree walk. This is exactly the behavior wanted in many cases
+ * --- and for those walkers that do want to recurse into sub-selects, special
+ * behavior is typically needed anyway at the entry to a sub-select (such as
+ * incrementing a depth counter). A walker that wants to examine sub-selects
+ * should include code along the lines of:
  *
  *             if (IsA(node, Query))
  *             {
@@ -2113,10 +2113,12 @@ substitute_actual_parameters_mutator(Node *node,
  * query_tree_walker is a convenience routine (see below) that calls the
  * walker on all the expression subtrees of the given Query node.
  *
- * NOTE: currently, because make_subplan() clears the subselect link in
- * a SubLink node, it is not actually possible to recurse into subselects
- * of an already-planned expression tree.  This is OK for current uses,
- * but ought to be cleaned up when we redesign querytree processing.
+ * expression_tree_walker will handle SubPlan nodes by recursing normally
+ * into the "oper" and "args" lists (which are expressions belonging to the
+ * outer plan).  It will not touch the completed subplan, however.  Since
+ * there is no link to the original Query, it is not possible to recurse into
+ * subselects of an already-planned expression tree.  This is OK for current
+ * uses, but may need to be revisited in future.
  *--------------------
  */
 
@@ -2207,24 +2209,13 @@ expression_tree_walker(Node *node,
                                SubLink    *sublink = (SubLink *) node;
 
                                /*
-                                * If the SubLink has already been processed by
-                                * subselect.c, it will have lefthand=NIL, and we need to
-                                * scan the oper list.  Otherwise we only need to look at
-                                * the lefthand list (the incomplete OpExpr nodes in the
-                                * oper list are deemed uninteresting, perhaps even
-                                * confusing).
+                                * We only recurse into the lefthand list (the incomplete
+                                * OpExpr nodes in the oper list are deemed uninteresting,
+                                * perhaps even confusing).
                                 */
-                               if (sublink->lefthand)
-                               {
-                                       if (walker((Node *) sublink->lefthand, context))
-                                               return true;
-                               }
-                               else
-                               {
-                                       if (walker((Node *) sublink->oper, context))
-                                               return true;
-                               }
-
+                               if (expression_tree_walker((Node *) sublink->lefthand,
+                                                                                  walker, context))
+                                       return true;
                                /*
                                 * Also invoke the walker on the sublink's Query node, so
                                 * it can recurse into the sub-query if it wants to.
@@ -2232,15 +2223,16 @@ expression_tree_walker(Node *node,
                                return walker(sublink->subselect, context);
                        }
                        break;
-               case T_SubPlanExpr:
+               case T_SubPlan:
                        {
-                               SubPlanExpr *expr = (SubPlanExpr *) node;
+                               SubPlan *subplan = (SubPlan *) node;
 
-                               /* recurse to the SubLink node, but not into the Plan */
-                               if (walker((Node *) expr->sublink, context))
+                               /* recurse into the oper list, but not into the Plan */
+                               if (expression_tree_walker((Node *) subplan->oper,
+                                                                                  walker, context))
                                        return true;
                                /* also examine args list */
-                               if (expression_tree_walker((Node *) expr->args,
+                               if (expression_tree_walker((Node *) subplan->args,
                                                                                   walker, context))
                                        return true;
                        }
@@ -2442,18 +2434,17 @@ query_tree_walker(Query *query,
  * expression_tree_mutator include all those normally found in target lists
  * and qualifier clauses during the planning stage.
  *
- * expression_tree_mutator will handle a SubPlanExpr node by recursing into
- * the args and sublink->oper lists (which belong to the outer plan), but it
+ * expression_tree_mutator will handle a SubPlan node by recursing into
+ * the "oper" and "args" lists (which belong to the outer plan), but it
  * will simply copy the link to the inner plan, since that's typically what
  * expression tree mutators want.  A mutator that wants to modify the subplan
- * can force appropriate behavior by recognizing subplan expression nodes
+ * can force appropriate behavior by recognizing SubPlan expression nodes
  * and doing the right thing.
  *
- * Bare SubLink nodes (without a SubPlanExpr) are handled by recursing into
- * the "lefthand" argument list only.  (A bare SubLink should be seen only if
- * the tree has not yet been processed by subselect.c.)  Again, this can be
- * overridden by the mutator, but it seems to be the most useful default
- * behavior.
+ * SubLink nodes are handled by recursing into the "lefthand" argument list
+ * only.  (A SubLink will be seen only if the tree has not yet been
+ * processed by subselect.c.)  Again, this can be overridden by the mutator,
+ * but it seems to be the most useful default behavior.
  *--------------------
  */
 
@@ -2560,9 +2551,8 @@ expression_tree_mutator(Node *node,
                case T_SubLink:
                        {
                                /*
-                                * A "bare" SubLink (note we will not come here if we
-                                * found a SubPlanExpr node above it).  Transform the
-                                * lefthand side, but not the oper list nor the subquery.
+                                * We transform the lefthand side, but not the oper list nor
+                                * the subquery.
                                 */
                                SubLink    *sublink = (SubLink *) node;
                                SubLink    *newnode;
@@ -2572,20 +2562,17 @@ expression_tree_mutator(Node *node,
                                return (Node *) newnode;
                        }
                        break;
-               case T_SubPlanExpr:
+               case T_SubPlan:
                        {
-                               SubPlanExpr   *expr = (SubPlanExpr *) node;
-                               SubLink           *oldsublink = expr->sublink;
-                               SubPlanExpr   *newnode;
+                               SubPlan    *subplan = (SubPlan *) node;
+                               SubPlan    *newnode;
 
-                               FLATCOPY(newnode, expr, SubPlanExpr);
-                               /* flat-copy the SubLink node */
-                               CHECKFLATCOPY(newnode->sublink, oldsublink, SubLink);
+                               FLATCOPY(newnode, subplan, SubPlan);
                                /* transform args list (params to be passed to subplan) */
-                               MUTATE(newnode->args, expr->args, List *);
-                               /* transform sublink's oper list as well */
-                               MUTATE(newnode->sublink->oper, oldsublink->oper, List *);
-                               /* but not the subplan itself, which is referenced as-is */
+                               MUTATE(newnode->args, subplan->args, List *);
+                               /* transform oper list as well */
+                               MUTATE(newnode->oper, subplan->oper, List *);
+                               /* but not the sub-Plan itself, which is referenced as-is */
                                return (Node *) newnode;
                        }
                        break;
index 8d22aa2..e4868af 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.41 2002/12/12 15:49:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.42 2002/12/14 00:17:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -65,7 +65,7 @@ static Node *flatten_join_alias_vars_mutator(Node *node,
  * NOTE: this is used on not-yet-planned expressions.  It may therefore find
  * bare SubLinks, and if so it needs to recurse into them to look for uplevel
  * references to the desired rtable level!     But when we find a completed
- * SubPlanExpr, we only need to look at the parameters passed to the subplan.
+ * SubPlan, we only need to look at the parameters passed to the subplan.
  */
 List *
 pull_varnos(Node *node)
@@ -111,9 +111,9 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
                 * executed by the outer query.  But short-circuit recursion into
                 * the subquery itself, which would be a waste of effort.
                 */
-               SubPlanExpr *subplan = (SubPlanExpr *) node;
+               SubPlan *subplan = (SubPlan *) node;
 
-               if (pull_varnos_walker((Node *) subplan->sublink->oper,
+               if (pull_varnos_walker((Node *) subplan->oper,
                                                           context))
                        return true;
                if (pull_varnos_walker((Node *) subplan->args,
@@ -146,7 +146,7 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
  * NOTE: this is used on not-yet-planned expressions.  It may therefore find
  * bare SubLinks, and if so it needs to recurse into them to look for uplevel
  * references to the desired rtable entry!     But when we find a completed
- * SubPlanExpr, we only need to look at the parameters passed to the subplan.
+ * SubPlan, we only need to look at the parameters passed to the subplan.
  */
 bool
 contain_var_reference(Node *node, int varno, int varattno, int levelsup)
@@ -194,9 +194,9 @@ contain_var_reference_walker(Node *node,
                 * executed by the outer query.  But short-circuit recursion into
                 * the subquery itself, which would be a waste of effort.
                 */
-               SubPlanExpr *subplan = (SubPlanExpr *) node;
+               SubPlan *subplan = (SubPlan *) node;
 
-               if (contain_var_reference_walker((Node *) subplan->sublink->oper,
+               if (contain_var_reference_walker((Node *) subplan->oper,
                                                                                 context))
                        return true;
                if (contain_var_reference_walker((Node *) subplan->args,
index 92f69a3..2fecab9 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.128 2002/12/12 15:49:40 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.129 2002/12/14 00:17:59 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -2099,7 +2099,7 @@ get_rule_expr(Node *node, deparse_context *context,
                        get_sublink_expr((SubLink *) node, context);
                        break;
 
-               case T_SubPlanExpr:
+               case T_SubPlan:
                        {
                                /*
                                 * We cannot see an already-planned subplan in
index bdcb3a6..9b7af6d 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.82 2002/12/13 19:45:56 tgl Exp $
+ * $Id: executor.h,v 1.83 2002/12/14 00:17:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -92,8 +92,7 @@ extern Datum ExecEvalExpr(ExprState *expression, ExprContext *econtext,
 extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
                                                  bool *isNull, ExprDoneCond *isDone);
 extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
-extern SubPlanExprState *ExecInitExprInitPlan(SubPlanExpr *node,
-                                                                                         PlanState *parent);
+extern SubPlanState *ExecInitExprInitPlan(SubPlan *node, PlanState *parent);
 extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
 extern int     ExecTargetListLength(List *targetlist);
 extern int     ExecCleanTargetListLength(List *targetlist);
index 97f4b66..8a3e74e 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: nodeSubplan.h,v 1.14 2002/12/13 19:45:56 tgl Exp $
+ * $Id: nodeSubplan.h,v 1.15 2002/12/14 00:17:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "nodes/execnodes.h"
 
-extern void ExecInitSubPlan(SubPlanExprState *sstate, EState *estate);
-extern Datum ExecSubPlan(SubPlanExprState *node,
+extern void ExecInitSubPlan(SubPlanState *node, EState *estate);
+extern Datum ExecSubPlan(SubPlanState *node,
                                                 ExprContext *econtext,
                                                 bool *isNull);
-extern void ExecEndSubPlan(SubPlanExprState *node);
-extern void ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent);
+extern void ExecEndSubPlan(SubPlanState *node);
+extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
 
-extern void ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext);
+extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
 
 #endif   /* NODESUBPLAN_H */
index 905bfae..f8e1f7c 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.84 2002/12/13 19:45:57 tgl Exp $
+ * $Id: execnodes.h,v 1.85 2002/12/14 00:17:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -451,21 +451,18 @@ typedef struct BoolExprState
 } BoolExprState;
 
 /* ----------------
- *             SubPlanExprState node
- *
- * Note: there is no separate ExprState node for the SubLink.  All it would
- * need is the oper field, which we can just as easily put here.
+ *             SubPlanState node
  * ----------------
  */
-typedef struct SubPlanExprState
+typedef struct SubPlanState
 {
        ExprState       xprstate;
        struct PlanState *planstate; /* subselect plan's state tree */
        bool            needShutdown;   /* TRUE = need to shutdown subplan */
        HeapTuple       curTuple;               /* copy of most recent tuple from subplan */
-       List       *args;                       /* states of argument expression(s) */
        List       *oper;                       /* states for executable combining exprs */
-} SubPlanExprState;
+       List       *args;                       /* states of argument expression(s) */
+} SubPlanState;
 
 /* ----------------
  *             CaseExprState node
@@ -538,9 +535,9 @@ typedef struct PlanState
        List       *qual;                       /* implicitly-ANDed qual conditions */
        struct PlanState *lefttree;     /* input plan tree(s) */
        struct PlanState *righttree;
-       List       *initPlan;           /* Init SubPlanExprState nodes (un-correlated
+       List       *initPlan;           /* Init SubPlanState nodes (un-correlated
                                                                 * expr subselects) */
-       List       *subPlan;            /* SubPlanExprState nodes in my expressions */
+       List       *subPlan;            /* SubPlanState nodes in my expressions */
 
        /*
         * State for management of parameter-change-driven rescanning
index cc55013..5f62816 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.132 2002/12/13 19:46:00 tgl Exp $
+ * $Id: nodes.h,v 1.133 2002/12/14 00:17:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -107,7 +107,7 @@ typedef enum NodeTag
        T_DistinctExpr,
        T_BoolExpr,
        T_SubLink,
-       T_SubPlanExpr,
+       T_SubPlan,
        T_FieldSelect,
        T_RelabelType,
        T_CaseExpr,
@@ -133,7 +133,7 @@ typedef enum NodeTag
        T_ArrayRefExprState,
        T_FuncExprState,
        T_BoolExprState,
-       T_SubPlanExprState,
+       T_SubPlanState,
        T_CaseExprState,
        T_CaseWhenState,
        T_ConstraintTestState,
index c8bc285..8d7aa3a 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.20 2002/12/13 19:46:00 tgl Exp $
+ * $Id: params.h,v 1.21 2002/12/14 00:17:59 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 SubPlanExprState node that needs
+ *       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 "SubPlanExprState *" */
+       void       *execPlan;           /* should be "SubPlanState *" */
        Datum           value;
        bool            isnull;
 } ParamExecData;
index 01a6dbf..285a000 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.74 2002/12/13 19:46:00 tgl Exp $
+ * $Id: primnodes.h,v 1.75 2002/12/14 00:17:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -378,32 +378,21 @@ typedef struct BoolExpr
  * using AND and OR semantics respectively.
  *
  * SubLink is classed as an Expr node, but it is not actually executable;
- * it must be replaced in the expression tree by a SubPlanExpr node during
+ * it must be replaced in the expression tree by a SubPlan node during
  * planning.
  *
- * NOTE: lefthand and oper have varying meanings depending on where you look
- * in the parse/plan pipeline:
- * 1. gram.y delivers a list of the (untransformed) lefthand expressions in
- *       lefthand, and sets oper to a single A_Expr (not a list!) containing
- *       the string name of the operator, but no arguments.
- * 2. The parser's expression transformation transforms lefthand normally,
- *       and replaces oper with a list of OpExpr nodes, one per lefthand
- *       expression.  These nodes represent the parser's resolution of exactly
- *       which operator to apply to each pair of lefthand and targetlist
- *       expressions.  However, we have not constructed complete Expr trees for
- *       these operations yet: the args fields of the OpExpr nodes are NIL.
- *       This is the representation seen in saved rules and in the rewriter.
- * 3. Finally, the planner converts the oper list to a list of normal OpExpr
- *       nodes representing the application of the operator(s) to the lefthand
- *       expressions and values from the inner targetlist.  The inner
- *       targetlist items are represented by placeholder Param nodes.
- *       The lefthand field is set to NIL, since its expressions are now in
- *       the Expr list.  This representation is passed to the executor.
- *
- * Planner routines that might see either representation 2 or 3 can tell
- * the difference by checking whether lefthand is NIL or not.  Also,
- * representation 2 appears in a "bare" SubLink, while representation 3 is
- * found in SubLinks that are children of SubPlanExpr nodes.
+ * NOTE: in the raw output of gram.y, lefthand contains a list of (raw)
+ * expressions, and oper contains a single A_Expr (not a list!) containing
+ * the string name of the operator, but no arguments.  Also, subselect is
+ * a raw parsetree.  During parse analysis, the parser transforms the
+ * lefthand expression list using normal expression transformation rules.
+ * It replaces oper with a list of OpExpr nodes, one per lefthand expression.
+ * These nodes represent the parser's resolution of exactly which operator
+ * to apply to each pair of lefthand and targetlist expressions.  However,
+ * we have not constructed complete Expr trees for these operations yet:
+ * the args fields of the OpExpr nodes are NIL.  And subselect is transformed
+ * to a Query.  This is the representation seen in saved rules and in the
+ * rewriter.
  *
  * In EXISTS and EXPR SubLinks, both lefthand and oper are unused and are
  * always NIL. useor is not significant either for these sublink types.
@@ -423,37 +412,58 @@ typedef struct SubLink
                                                                 * "OR" not "AND" */
        List       *lefthand;           /* list of outer-query expressions on the
                                                                 * left */
-       List       *oper;                       /* list of OpExpr nodes for combining
-                                                                * operators, or final list of executable
-                                                                * expressions */
+       List       *oper;                       /* list of arg-less OpExpr nodes for
+                                                                * combining operators */
        Node       *subselect;          /* subselect as Query* or parsetree */
 } SubLink;
 
 /*
- * SubPlanExpr - executable expression node for a subplan (sub-SELECT)
- *
- * The planner replaces SubLink nodes in expression trees with SubPlanExpr
- * nodes after it has finished planning the subquery.  See notes above.
- */
-typedef struct SubPlanExpr
+ * SubPlan - executable expression node for a subplan (sub-SELECT)
+ *
+ * The planner replaces SubLink nodes in expression trees with SubPlan
+ * nodes after it has finished planning the subquery.  SubPlan contains
+ * a sub-plantree and rtable instead of a sub-Query.  Its "oper" field
+ * corresponds to the original SubLink's oper list, but has been expanded
+ * into valid executable expressions representing the application of the
+ * combining operator(s) to the lefthand expressions and values from the
+ * inner targetlist.  The original lefthand expressions now appear as
+ * left-hand arguments of the OpExpr nodes, while the inner targetlist items
+ * are represented by PARAM_EXEC Param nodes.  (Note: if the sub-select
+ * becomes an InitPlan rather than a SubPlan, the rebuilt oper list is
+ * part of the outer plan tree and so is not stored in the oper field.)
+ *
+ * The planner also derives lists of the values that need to be passed into
+ * and out of the subplan.  Input values are represented as a list "args" of
+ * expressions to be evaluated in the outer-query context (currently these
+ * args are always just Vars, but in principle they could be any expression).
+ * The values are assigned to the global PARAM_EXEC params indexed by parParam
+ * (the parParam and args lists must have the same length).  setParam is a
+ * list of the PARAM_EXEC params that are computed by the sub-select, if it
+ * is an initPlan.
+ */
+typedef struct SubPlan
 {
        Expr            xpr;
-       Oid                     typeOid;                /* PG_TYPE OID of the expression result */
+       /* Fields copied from original SubLink: */
+       SubLinkType subLinkType;        /* EXISTS, ALL, ANY, MULTIEXPR, EXPR */
+       bool            useor;                  /* TRUE to combine column results with
+                                                                * "OR" not "AND" */
+       List       *oper;                       /* list of executable expressions for
+                                                                * combining operators (with arguments) */
+       /* The subselect, transformed to a Plan: */
        struct Plan *plan;                      /* subselect plan itself */
        int                     plan_id;                /* dummy thing because of we haven't equal
                                                                 * funcs for plan nodes... actually, we
                                                                 * could put *plan itself somewhere else
                                                                 * (TopPlan node ?)... */
        List       *rtable;                     /* range table for subselect */
+       /* Information for passing params into and out of the subselect: */
        /* setParam and parParam are lists of integers (param IDs) */
        List       *setParam;           /* non-correlated EXPR & EXISTS subqueries
                                                                 * have to set some Params for paren Plan */
        List       *parParam;           /* indices of input Params from parent plan */
        List       *args;                       /* exprs to pass as parParam values */
-       SubLink    *sublink;            /* SubLink node from parser; holds info
-                                                                * about what to do with subselect's
-                                                                * results */
-} SubPlanExpr;
+} SubPlan;
 
 /* ----------------
  * FieldSelect
index 8da7a86..f280e42 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: clauses.h,v 1.57 2002/12/12 15:49:41 tgl Exp $
+ * $Id: clauses.h,v 1.58 2002/12/14 00:17:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,7 @@
 
 #define is_opclause(clause)            ((clause) != NULL && IsA(clause, OpExpr))
 #define is_funcclause(clause)  ((clause) != NULL && IsA(clause, FuncExpr))
-#define is_subplan(clause)             ((clause) != NULL && IsA(clause, SubPlanExpr))
+#define is_subplan(clause)             ((clause) != NULL && IsA(clause, SubPlan))
 
 
 extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,