summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/setrefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r--src/backend/optimizer/plan/setrefs.c83
1 files changed, 32 insertions, 51 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index b44aa6408b8..756333e0059 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.60 2000/01/26 05:56:38 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.61 2000/04/04 01:21:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,6 +59,8 @@ 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.
*
@@ -72,6 +74,11 @@ set_plan_references(Plan *plan)
if (plan == NULL)
return;
+ /* We must rebuild the plan's list of subplan nodes, since we are
+ * copying/mutating its expression trees.
+ */
+ plan->subPlan = NIL;
+
/*
* Plan-type-specific fixes
*/
@@ -83,6 +90,12 @@ set_plan_references(Plan *plan)
case T_IndexScan:
fix_opids((Node *) ((IndexScan *) plan)->indxqual);
fix_opids((Node *) ((IndexScan *) plan)->indxqualorig);
+ plan->subPlan =
+ nconc(plan->subPlan,
+ pull_subplans((Node *) ((IndexScan *) plan)->indxqual));
+ plan->subPlan =
+ nconc(plan->subPlan,
+ pull_subplans((Node *) ((IndexScan *) plan)->indxqualorig));
break;
case T_NestLoop:
set_join_references((Join *) plan);
@@ -90,10 +103,16 @@ set_plan_references(Plan *plan)
case T_MergeJoin:
set_join_references((Join *) plan);
fix_opids((Node *) ((MergeJoin *) plan)->mergeclauses);
+ plan->subPlan =
+ nconc(plan->subPlan,
+ pull_subplans((Node *) ((MergeJoin *) plan)->mergeclauses));
break;
case T_HashJoin:
set_join_references((Join *) plan);
fix_opids((Node *) ((HashJoin *) plan)->hashclauses);
+ plan->subPlan =
+ nconc(plan->subPlan,
+ pull_subplans((Node *) ((HashJoin *) plan)->hashclauses));
break;
case T_Material:
case T_Sort:
@@ -119,6 +138,9 @@ set_plan_references(Plan *plan)
if (plan->lefttree != NULL)
set_uppernode_references(plan, (Index) OUTER);
fix_opids(((Result *) plan)->resconstantqual);
+ plan->subPlan =
+ nconc(plan->subPlan,
+ pull_subplans(((Result *) plan)->resconstantqual));
break;
case T_Append:
foreach(pl, ((Append *) plan)->appendplans)
@@ -136,10 +158,17 @@ set_plan_references(Plan *plan)
}
/*
- * For all plan types, fix operators in targetlist and qual expressions
+ * For all plan types, fix operators in targetlist and qual expressions,
+ * and find subplans therein.
*/
fix_opids((Node *) plan->targetlist);
fix_opids((Node *) plan->qual);
+ plan->subPlan =
+ nconc(plan->subPlan,
+ pull_subplans((Node *) plan->targetlist));
+ plan->subPlan =
+ nconc(plan->subPlan,
+ pull_subplans((Node *) plan->qual));
/*
* Now recurse into subplans, if any
@@ -302,31 +331,7 @@ join_references_mutator(Node *node,
*/
if (var->varno != context->acceptable_rel)
elog(ERROR, "join_references: variable not in subplan target lists");
- return (Node *) newvar; /* copy is probably not necessary here... */
- }
- /*
- * expression_tree_mutator will copy SubPlan nodes if given a chance.
- * We do not want to do that here, because subselect.c has already
- * constructed the initPlan and subPlan lists of the current plan node
- * and we mustn't leave those dangling (ie, pointing to different
- * copies of the nodes than what's in the targetlist & quals...)
- * Instead, alter the SubPlan in-place. Grotty --- is there a better way?
- */
- if (is_subplan(node))
- {
- Expr *expr = (Expr *) node;
- SubLink *sublink = ((SubPlan *) expr->oper)->sublink;
-
- /* transform args list (params to be passed to subplan) */
- expr->args = (List *)
- join_references_mutator((Node *) expr->args,
- context);
- /* transform sublink's oper list as well */
- sublink->oper = (List *)
- join_references_mutator((Node *) sublink->oper,
- context);
-
- return (Node *) expr;
+ return (Node *) newvar;
}
return expression_tree_mutator(node,
join_references_mutator,
@@ -383,30 +388,6 @@ replace_vars_with_subplan_refs_mutator(Node *node,
newvar->varattno = resdom->resno;
return (Node *) newvar;
}
- /*
- * expression_tree_mutator will copy SubPlan nodes if given a chance.
- * We do not want to do that here, because subselect.c has already
- * constructed the initPlan and subPlan lists of the current plan node
- * and we mustn't leave those dangling (ie, pointing to different
- * copies of the nodes than what's in the targetlist & quals...)
- * Instead, alter the SubPlan in-place. Grotty --- is there a better way?
- */
- if (is_subplan(node))
- {
- Expr *expr = (Expr *) node;
- SubLink *sublink = ((SubPlan *) expr->oper)->sublink;
-
- /* transform args list (params to be passed to subplan) */
- expr->args = (List *)
- replace_vars_with_subplan_refs_mutator((Node *) expr->args,
- context);
- /* transform sublink's oper list as well */
- sublink->oper = (List *)
- replace_vars_with_subplan_refs_mutator((Node *) sublink->oper,
- context);
-
- return (Node *) expr;
- }
return expression_tree_mutator(node,
replace_vars_with_subplan_refs_mutator,
(void *) context);