diff options
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 3db73e87f0b..b23843a030c 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.83 2002/11/30 21:25:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.84 2002/12/05 15:50:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,6 +41,7 @@ typedef struct } replace_vars_with_subplan_refs_context; static void fix_expr_references(Plan *plan, Node *node); +static bool fix_expr_references_walker(Node *node, void *context); static void set_join_references(Join *join, List *rtable); static void set_uppernode_references(Plan *plan, Index subvarno); static Node *join_references_mutator(Node *node, @@ -66,8 +67,6 @@ static bool fix_opids_walker(Node *node, void *context); * for the convenience of the executor. We update Vars in upper plan nodes * to refer to the outputs of their subplans, and we compute regproc OIDs * for operators (ie, we look up the function that implements each op). - * We must also build lists of all the subplan nodes present in each - * plan node's expression trees. * * set_plan_references recursively traverses the whole plan tree. * @@ -82,12 +81,6 @@ set_plan_references(Plan *plan, List *rtable) return; /* - * We must rebuild the plan's list of subplan nodes, since we are - * copying/mutating its expression trees. - */ - plan->subPlan = NIL; - - /* * Plan-type-specific fixes */ switch (nodeTag(plan)) @@ -107,6 +100,8 @@ set_plan_references(Plan *plan, List *rtable) case T_TidScan: fix_expr_references(plan, (Node *) plan->targetlist); fix_expr_references(plan, (Node *) plan->qual); + fix_expr_references(plan, + (Node *) ((TidScan *) plan)->tideval); break; case T_SubqueryScan: { @@ -175,9 +170,9 @@ set_plan_references(Plan *plan, List *rtable) * unmodified input tuples). The optimizer is lazy about * creating really valid targetlists for them. Best to just * leave the targetlist alone. In particular, we do not want - * to pull a subplan list for them, since we will likely end - * up with duplicate list entries for subplans that also - * appear in lower levels of the plan tree! + * to process subplans for them, since we will likely end + * up reprocessing subplans that also appear in lower levels + * of the plan tree! */ break; case T_Agg: @@ -206,7 +201,7 @@ set_plan_references(Plan *plan, List *rtable) * Append, like Sort et al, doesn't actually evaluate its * targetlist or quals, and we haven't bothered to give it its * own tlist copy. So, don't fix targetlist/qual. But do - * recurse into subplans. + * recurse into child plans. */ foreach(pl, ((Append *) plan)->appendplans) set_plan_references((Plan *) lfirst(pl), rtable); @@ -218,24 +213,19 @@ set_plan_references(Plan *plan, List *rtable) } /* - * Now recurse into subplans, if any + * Now recurse into child plans and initplans, if any * - * NOTE: it is essential that we recurse into subplans AFTER we set + * NOTE: it is essential that we recurse into child plans AFTER we set * subplan references in this plan's tlist and quals. If we did the * reference-adjustments bottom-up, then we would fail to match this * plan's var nodes against the already-modified nodes of the - * subplans. + * children. Fortunately, that consideration doesn't apply to SubPlan + * nodes; else we'd need two passes over the expression trees. */ set_plan_references(plan->lefttree, rtable); set_plan_references(plan->righttree, rtable); - foreach(pl, plan->initPlan) - { - SubPlan *sp = (SubPlan *) lfirst(pl); - Assert(IsA(sp, SubPlan)); - set_plan_references(sp->plan, sp->rtable); - } - foreach(pl, plan->subPlan) + foreach(pl, plan->initPlan) { SubPlan *sp = (SubPlan *) lfirst(pl); @@ -249,13 +239,38 @@ set_plan_references(Plan *plan, List *rtable) * Do final cleanup on expressions (targetlists or quals). * * This consists of looking up operator opcode info for Oper nodes - * and adding subplans to the Plan node's list of contained subplans. + * and recursively performing set_plan_references on SubPlans. + * + * The Plan argument is currently unused, but might be needed again someday. */ static void fix_expr_references(Plan *plan, Node *node) { - fix_opids(node); - plan->subPlan = nconc(plan->subPlan, pull_subplans(node)); + /* This tree walk requires no special setup, so away we go... */ + fix_expr_references_walker(node, NULL); +} + +static bool +fix_expr_references_walker(Node *node, void *context) +{ + if (node == NULL) + return false; + if (IsA(node, Expr)) + { + Expr *expr = (Expr *) node; + + if (expr->opType == OP_EXPR || + expr->opType == DISTINCT_EXPR) + replace_opid((Oper *) expr->oper); + else if (expr->opType == SUBPLAN_EXPR) + { + SubPlan *sp = (SubPlan *) expr->oper; + + Assert(IsA(sp, SubPlan)); + set_plan_references(sp->plan, sp->rtable); + } + } + return expression_tree_walker(node, fix_expr_references_walker, context); } /* |