diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-04-11 23:06:57 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-04-11 23:06:57 +0000 |
commit | addc42c339208d6a7a1d652fbf388e8aea7f80b9 (patch) | |
tree | e349d31f2ae1006ed4078b811dae8d842e00d969 /src/backend/optimizer/plan/subselect.c | |
parent | c3294f1cbfe02293b4a7c6b2e58ca4c09a7e541f (diff) |
Create the planner mechanism for optimizing simple MIN and MAX queries
into indexscans on matching indexes. For the moment, it only handles
int4 and text datatypes; next step is to add a column to pg_aggregate
so that all MIN/MAX aggregates can be handled. Per my recent proposal.
Diffstat (limited to 'src/backend/optimizer/plan/subselect.c')
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 107 |
1 files changed, 104 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index c92fb315316..f1519569a85 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 - * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.95 2005/04/06 16:34:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.96 2005/04/11 23:06:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -915,14 +915,16 @@ process_sublinks_mutator(Node *node, bool *isTopQual) /* * SS_finalize_plan - do final sublink processing for a completed Plan. * - * This recursively computes the extParam and allParam sets - * for every Plan node in the given plan tree. + * This recursively computes the extParam and allParam sets for every Plan + * node in the given plan tree. It also attaches any generated InitPlans + * to the top plan node. */ void SS_finalize_plan(Plan *plan, List *rtable) { Bitmapset *outer_params = NULL; Bitmapset *valid_params = NULL; + Cost initplan_cost = 0; int paramid; ListCell *l; @@ -959,6 +961,33 @@ SS_finalize_plan(Plan *plan, List *rtable) bms_free(outer_params); bms_free(valid_params); + + /* + * Finally, attach any initPlans to the topmost plan node, + * and add their extParams to the topmost node's, too. + * + * We also add the total_cost of each initPlan to the startup cost of + * the top node. This is a conservative overestimate, since in + * fact each initPlan might be executed later than plan startup, + * or even not at all. + */ + plan->initPlan = PlannerInitPlan; + PlannerInitPlan = NIL; /* make sure they're not attached twice */ + + foreach(l, plan->initPlan) + { + SubPlan *initplan = (SubPlan *) lfirst(l); + + plan->extParam = bms_add_members(plan->extParam, + initplan->plan->extParam); + /* allParam must include all members of extParam */ + plan->allParam = bms_add_members(plan->allParam, + plan->extParam); + initplan_cost += initplan->plan->total_cost; + } + + plan->startup_cost += initplan_cost; + plan->total_cost += initplan_cost; } /* @@ -1165,3 +1194,75 @@ finalize_primnode(Node *node, finalize_primnode_context *context) return expression_tree_walker(node, finalize_primnode, (void *) context); } + +/* + * SS_make_initplan_from_plan - given a plan tree, make it an InitPlan + * + * The plan is expected to return a scalar value of the indicated type. + * We build an EXPR_SUBLINK SubPlan node and put it into the initplan + * list for the current query level. A Param that represents the initplan's + * output is returned. + * + * We assume the plan hasn't been put through SS_finalize_plan. + */ +Param * +SS_make_initplan_from_plan(Query *root, Plan *plan, + Oid resulttype, int32 resulttypmod) +{ + List *saved_initplan = PlannerInitPlan; + SubPlan *node; + Param *prm; + Bitmapset *tmpset; + int paramid; + + /* + * Set up for a new level of subquery. This is just to keep + * SS_finalize_plan from becoming confused. + */ + PlannerQueryLevel++; + PlannerInitPlan = NIL; + + /* + * Build extParam/allParam sets for plan nodes. + */ + SS_finalize_plan(plan, root->rtable); + + /* Return to outer subquery context */ + PlannerQueryLevel--; + PlannerInitPlan = saved_initplan; + + /* + * Create a SubPlan node and add it to the outer list of InitPlans. + */ + node = makeNode(SubPlan); + node->subLinkType = EXPR_SUBLINK; + node->plan = plan; + node->plan_id = PlannerPlanId++; /* Assign unique ID to this + * SubPlan */ + + node->rtable = root->rtable; + + PlannerInitPlan = lappend(PlannerInitPlan, node); + + /* + * Make parParam list of params that current query level will pass to + * this child plan. (In current usage there probably aren't any.) + */ + tmpset = bms_copy(plan->extParam); + while ((paramid = bms_first_member(tmpset)) >= 0) + { + PlannerParamItem *pitem = list_nth(PlannerParamList, paramid); + + if (pitem->abslevel == PlannerQueryLevel) + node->parParam = lappend_int(node->parParam, paramid); + } + bms_free(tmpset); + + /* + * Make a Param that will be the subplan's output. + */ + prm = generate_new_param(resulttype, resulttypmod); + node->setParam = list_make1_int(prm->paramid); + + return prm; +} |