diff options
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 19 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 41 | ||||
-rw-r--r-- | src/backend/optimizer/path/equivclass.c | 10 |
3 files changed, 62 insertions, 8 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index b0553894c24..17eebc67647 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.177 2008/11/15 19:43:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.178 2008/12/28 18:53:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -929,10 +929,13 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels) * 1. If the subquery has a LIMIT clause, we must not push down any quals, * since that could change the set of rows returned. * - * 2. If the subquery contains EXCEPT or EXCEPT ALL set ops we cannot push + * 2. If the subquery contains any window functions, we can't push quals + * into it, because that would change the results. + * + * 3. If the subquery contains EXCEPT or EXCEPT ALL set ops we cannot push * quals into it, because that would change the results. * - * 3. For subqueries using UNION/UNION ALL/INTERSECT/INTERSECT ALL, we can + * 4. For subqueries using UNION/UNION ALL/INTERSECT/INTERSECT ALL, we can * push quals into each component query, but the quals can only reference * subquery columns that suffer no type coercions in the set operation. * Otherwise there are possible semantic gotchas. So, we check the @@ -950,6 +953,10 @@ subquery_is_pushdown_safe(Query *subquery, Query *topquery, if (subquery->limitOffset != NULL || subquery->limitCount != NULL) return false; + /* Check point 2 */ + if (subquery->hasWindowFuncs) + return false; + /* Are we at top level, or looking at a setop component? */ if (subquery == topquery) { @@ -1093,6 +1100,12 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual, return false; /* + * It would be unsafe to push down window function calls, but at least + * for the moment we could never see any in a qual anyhow. + */ + Assert(!contain_window_function(qual)); + + /* * Examine all Vars used in clause; since it's a restriction clause, all * such Vars must refer to subselect output columns. */ diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 0b9c5819820..7f30dde869f 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -54,7 +54,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.201 2008/11/22 22:47:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.202 2008/12/28 18:53:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1284,6 +1284,40 @@ cost_agg(Path *path, PlannerInfo *root, } /* + * cost_windowagg + * Determines and returns the cost of performing a WindowAgg plan node, + * including the cost of its input. + * + * Input is assumed already properly sorted. + */ +void +cost_windowagg(Path *path, PlannerInfo *root, + int numWindowFuncs, int numPartCols, int numOrderCols, + Cost input_startup_cost, Cost input_total_cost, + double input_tuples) +{ + Cost startup_cost; + Cost total_cost; + + startup_cost = input_startup_cost; + total_cost = input_total_cost; + + /* + * We charge one cpu_operator_cost per window function per tuple (often a + * drastic underestimate, but without a way to gauge how many tuples the + * window function will fetch, it's hard to do better). We also charge + * cpu_operator_cost per grouping column per tuple for grouping + * comparisons, plus cpu_tuple_cost per tuple for general overhead. + */ + total_cost += cpu_operator_cost * input_tuples * numWindowFuncs; + total_cost += cpu_operator_cost * input_tuples * (numPartCols + numOrderCols); + total_cost += cpu_tuple_cost * input_tuples; + + path->startup_cost = startup_cost; + path->total_cost = total_cost; +} + +/* * cost_group * Determines and returns the cost of performing a Group plan node, * including the cost of its input. @@ -2155,6 +2189,11 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) * Vars and Consts are charged zero, and so are boolean operators (AND, * OR, NOT). Simplistic, but a lot better than no model at all. * + * Note that Aggref and WindowFunc nodes are (and should be) treated + * like Vars --- whatever execution cost they have is absorbed into + * plan-node-specific costing. As far as expression evaluation is + * concerned they're just like Vars. + * * Should we try to account for the possibility of short-circuit * evaluation of AND/OR? Probably *not*, because that would make the * results depend on the clause ordering, and we are not in any position diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 3d35eb605d9..5f6d219a01a 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -10,7 +10,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.14 2008/12/01 21:06:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.15 2008/12/28 18:53:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -438,14 +438,16 @@ get_eclass_for_sort_expr(PlannerInfo *root, /* * add_eq_member doesn't check for volatile functions, set-returning - * functions, or aggregates, but such could appear in sort expressions; so - * we have to check whether its const-marking was correct. + * functions, aggregates, or window functions, but such could appear + * in sort expressions; so we have to check whether its const-marking + * was correct. */ if (newec->ec_has_const) { if (newec->ec_has_volatile || expression_returns_set((Node *) expr) || - contain_agg_clause((Node *) expr)) + contain_agg_clause((Node *) expr) || + contain_window_function((Node *) expr)) { newec->ec_has_const = false; newem->em_is_const = false; |