diff options
Diffstat (limited to 'src/backend/optimizer/plan')
| -rw-r--r-- | src/backend/optimizer/plan/planner.c | 6 | ||||
| -rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 12 | ||||
| -rw-r--r-- | src/backend/optimizer/plan/subselect.c | 227 |
3 files changed, 130 insertions, 115 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index b3d7b5303c..b7c0c2ad4b 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 0d66c97964..5081f9c340 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 fe17b8ebb0..840ba975a3 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); +} |
