mirror of
https://github.com/postgres/postgres.git
synced 2025-08-19 23:22:23 +03:00
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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user