aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planagg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planagg.c')
-rw-r--r--src/backend/optimizer/plan/planagg.c85
1 files changed, 44 insertions, 41 deletions
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 38c859dfbcb..0a47799707c 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.4 2005/04/22 21:58:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.5 2005/06/05 22:32:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,11 +42,11 @@ typedef struct
} MinMaxAggInfo;
static bool find_minmax_aggs_walker(Node *node, List **context);
-static bool build_minmax_path(Query *root, RelOptInfo *rel,
+static bool build_minmax_path(PlannerInfo *root, RelOptInfo *rel,
MinMaxAggInfo *info);
static ScanDirection match_agg_to_index_col(MinMaxAggInfo *info,
IndexOptInfo *index, int indexcol);
-static void make_agg_subplan(Query *root, MinMaxAggInfo *info,
+static void make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info,
List *constant_quals);
static Node *replace_aggs_with_params_mutator(Node *node, List **context);
static Oid fetch_agg_sort_op(Oid aggfnoid);
@@ -61,15 +61,16 @@ static Oid fetch_agg_sort_op(Oid aggfnoid);
* Given a suitable index on tab.col, this can be much faster than the
* generic scan-all-the-rows plan.
*
- * We are passed the Query, the preprocessed tlist, and the best path
+ * We are passed the preprocessed tlist, and the best path
* devised for computing the input of a standard Agg node. If we are able
* to optimize all the aggregates, and the result is estimated to be cheaper
* than the generic aggregate method, then generate and return a Plan that
* does it that way. Otherwise, return NULL.
*/
Plan *
-optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
+optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path)
{
+ Query *parse = root->parse;
RangeTblRef *rtr;
RangeTblEntry *rte;
RelOptInfo *rel;
@@ -83,11 +84,11 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
List *constant_quals;
/* Nothing to do if query has no aggregates */
- if (!root->hasAggs)
+ if (!parse->hasAggs)
return NULL;
- Assert(!root->setOperations); /* shouldn't get here if a setop */
- Assert(root->rowMarks == NIL); /* nor if FOR UPDATE */
+ Assert(!parse->setOperations); /* shouldn't get here if a setop */
+ Assert(parse->rowMarks == NIL); /* nor if FOR UPDATE */
/*
* Reject unoptimizable cases.
@@ -96,7 +97,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
* grouping require looking at all the rows anyway, and so there's not
* much point in optimizing MIN/MAX.
*/
- if (root->groupClause)
+ if (parse->groupClause)
return NULL;
/*
@@ -105,13 +106,13 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
* handle a query containing cartesian-product joins, but it hardly
* seems worth the trouble.)
*/
- Assert(root->jointree != NULL && IsA(root->jointree, FromExpr));
- if (list_length(root->jointree->fromlist) != 1)
+ Assert(parse->jointree != NULL && IsA(parse->jointree, FromExpr));
+ if (list_length(parse->jointree->fromlist) != 1)
return NULL;
- rtr = (RangeTblRef *) linitial(root->jointree->fromlist);
+ rtr = (RangeTblRef *) linitial(parse->jointree->fromlist);
if (!IsA(rtr, RangeTblRef))
return NULL;
- rte = rt_fetch(rtr->rtindex, root->rtable);
+ rte = rt_fetch(rtr->rtindex, parse->rtable);
if (rte->rtekind != RTE_RELATION)
return NULL;
rel = find_base_rel(root, rtr->rtindex);
@@ -121,8 +122,8 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
* This may be overly paranoid, but it's not entirely clear if the
* transformation is safe then.
*/
- if (contain_subplans(root->jointree->quals) ||
- contain_volatile_functions(root->jointree->quals))
+ if (contain_subplans(parse->jointree->quals) ||
+ contain_volatile_functions(parse->jointree->quals))
return NULL;
/*
@@ -143,7 +144,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
aggs_list = NIL;
if (find_minmax_aggs_walker((Node *) tlist, &aggs_list))
return NULL;
- if (find_minmax_aggs_walker(root->havingQual, &aggs_list))
+ if (find_minmax_aggs_walker(parse->havingQual, &aggs_list))
return NULL;
/* Pass 2: see if each one is optimizable */
@@ -202,7 +203,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
*/
tlist = (List *) replace_aggs_with_params_mutator((Node *) tlist,
&aggs_list);
- hqual = replace_aggs_with_params_mutator(root->havingQual,
+ hqual = replace_aggs_with_params_mutator(parse->havingQual,
&aggs_list);
/*
@@ -298,7 +299,7 @@ find_minmax_aggs_walker(Node *node, List **context)
* Note: check_partial_indexes() must have been run previously.
*/
static bool
-build_minmax_path(Query *root, RelOptInfo *rel, MinMaxAggInfo *info)
+build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info)
{
IndexPath *best_path = NULL;
Cost best_cost = 0;
@@ -441,46 +442,48 @@ match_agg_to_index_col(MinMaxAggInfo *info, IndexOptInfo *index, int indexcol)
* Construct a suitable plan for a converted aggregate query
*/
static void
-make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals)
+make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info, List *constant_quals)
{
- Query *subquery;
+ PlannerInfo subroot;
+ Query *subparse;
Plan *plan;
TargetEntry *tle;
SortClause *sortcl;
NullTest *ntest;
/*
- * Generate a suitably modified Query node. Much of the work here is
+ * Generate a suitably modified query. Much of the work here is
* probably unnecessary in the normal case, but we want to make it look
* good if someone tries to EXPLAIN the result.
*/
- subquery = (Query *) copyObject(root);
- subquery->commandType = CMD_SELECT;
- subquery->resultRelation = 0;
- subquery->resultRelations = NIL;
- subquery->into = NULL;
- subquery->hasAggs = false;
- subquery->groupClause = NIL;
- subquery->havingQual = NULL;
- subquery->hasHavingQual = false;
- subquery->distinctClause = NIL;
+ memcpy(&subroot, root, sizeof(PlannerInfo));
+ subroot.parse = subparse = (Query *) copyObject(root->parse);
+ subparse->commandType = CMD_SELECT;
+ subparse->resultRelation = 0;
+ subparse->resultRelations = NIL;
+ subparse->into = NULL;
+ subparse->hasAggs = false;
+ subparse->groupClause = NIL;
+ subparse->havingQual = NULL;
+ subparse->distinctClause = NIL;
+ subroot.hasHavingQual = false;
/* single tlist entry that is the aggregate target */
tle = makeTargetEntry(copyObject(info->target),
1,
pstrdup("agg_target"),
false);
- subquery->targetList = list_make1(tle);
+ subparse->targetList = list_make1(tle);
/* set up the appropriate ORDER BY entry */
sortcl = makeNode(SortClause);
- sortcl->tleSortGroupRef = assignSortGroupRef(tle, subquery->targetList);
+ sortcl->tleSortGroupRef = assignSortGroupRef(tle, subparse->targetList);
sortcl->sortop = info->aggsortop;
- subquery->sortClause = list_make1(sortcl);
+ subparse->sortClause = list_make1(sortcl);
/* set up LIMIT 1 */
- subquery->limitOffset = NULL;
- subquery->limitCount = (Node *) makeConst(INT4OID, sizeof(int4),
+ subparse->limitOffset = NULL;
+ subparse->limitCount = (Node *) makeConst(INT4OID, sizeof(int4),
Int32GetDatum(1),
false, true);
@@ -498,9 +501,9 @@ make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals)
* most cases the fraction of NULLs isn't high enough to change the
* decision.
*/
- plan = create_plan(subquery, (Path *) info->path);
+ plan = create_plan(&subroot, (Path *) info->path);
- plan->targetlist = copyObject(subquery->targetList);
+ plan->targetlist = copyObject(subparse->targetList);
ntest = makeNode(NullTest);
ntest->nulltesttype = IS_NOT_NULL;
@@ -514,13 +517,13 @@ make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals)
plan);
plan = (Plan *) make_limit(plan,
- subquery->limitOffset,
- subquery->limitCount);
+ subparse->limitOffset,
+ subparse->limitCount);
/*
* Convert the plan into an InitPlan, and make a Param for its result.
*/
- info->param = SS_make_initplan_from_plan(subquery, plan,
+ info->param = SS_make_initplan_from_plan(&subroot, plan,
exprType((Node *) tle->expr),
-1);
}