diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-12-14 00:17:59 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-12-14 00:17:59 +0000 |
commit | 2d8d66628a8ac49deba8483608135b3c358ae729 (patch) | |
tree | 95f321c5fc2035b5110317e25b0449e85065c8a5 /src | |
parent | 29cdab3d531b6f612ab53b93dbb34a131e9cdb1c (diff) | |
download | postgresql-2d8d66628a8ac49deba8483608135b3c358ae729.tar.gz postgresql-2d8d66628a8ac49deba8483608135b3c358ae729.zip |
Clean up plantree representation of SubPlan-s --- SubLink does not appear
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.
Diffstat (limited to 'src')
24 files changed, 357 insertions, 358 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 1f9e7543d6f..05815a2201b 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -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++) diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index fa95ad6d992..c55e5ecd149 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -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) diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 59c798b267a..dc5a3085ead 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -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) { diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index b529d045c4d..a3f79c3ac80 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -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; diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 69fcc58e079..3a2ca974aee 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -30,15 +30,14 @@ * ---------------------------------------------------------------- */ 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; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index d84e6061246..c3abcfc9e80 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 3fc924024e2..5fc333df3de 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -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); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index a688b471e79..97fc9462a27 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 54e3916ebf6..9ecd40f2e1d 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -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. */ /* diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 114e8798856..5feaed49158 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -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 + diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index b3d7b5303c4..b7c0c2ad4b5 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -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); diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 0d66c97964c..5081f9c3401 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -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); } diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index fe17b8ebb01..840ba975a34 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -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); +} diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index a55af2e2d06..5e44a64c012 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -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; diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index af96615c7fc..1d87afdc42f 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -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; diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index 8d22aa26b91..e4868af11cd 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -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, diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 92f69a32a82..2fecab9655c 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -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 diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index bdcb3a6afa5..9b7af6d36fb 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -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); diff --git a/src/include/executor/nodeSubplan.h b/src/include/executor/nodeSubplan.h index 97f4b66bcd6..8a3e74ebd1c 100644 --- a/src/include/executor/nodeSubplan.h +++ b/src/include/executor/nodeSubplan.h @@ -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 $ * *------------------------------------------------------------------------- */ @@ -16,13 +16,13 @@ #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 */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 905bfae6d87..f8e1f7cc4c9 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -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 diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index cc550131852..5f628168738 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -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, diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h index c8bc2857ed8..8d7aa3ab32b 100644 --- a/src/include/nodes/params.h +++ b/src/include/nodes/params.h @@ -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; diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 01a6dbf8d64..285a0008fdc 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -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 diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index 8da7a8688ef..f280e420d9b 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -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, |