aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-11-06 22:31:24 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-11-06 22:31:24 +0000
commit2103b7baa26fe25cc2b5bee802028caeabb28113 (patch)
treef7516bbb3b18fca352fd638d567b2b0bf3a5a0bd /src/backend/optimizer
parentfc9814d17e7701bac198c99f8ab9f67c8468797f (diff)
downloadpostgresql-2103b7baa26fe25cc2b5bee802028caeabb28113.tar.gz
postgresql-2103b7baa26fe25cc2b5bee802028caeabb28113.zip
Phase 2 of hashed-aggregation project. nodeAgg.c now knows how to do
hashed aggregation, but there's not yet planner support for it.
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/plan/createplan.c3
-rw-r--r--src/backend/optimizer/plan/planner.c63
-rw-r--r--src/backend/optimizer/util/clauses.c29
3 files changed, 80 insertions, 15 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 5a2acbd2763..cba1b2027d3 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.120 2002/11/06 00:00:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.121 2002/11/06 22:31:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1675,6 +1675,7 @@ make_agg(List *tlist, List *qual, AggStrategy aggstrategy,
plan->plan_rows *= 0.1;
if (plan->plan_rows < 1)
plan->plan_rows = 1;
+ node->numGroups = (long) plan->plan_rows;
}
plan->state = (EState *) NULL;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index cc8e7a698d5..7e722d6a099 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.126 2002/11/06 00:00:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.127 2002/11/06 22:31:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -931,6 +931,7 @@ grouping_planner(Query *parse, double tuple_fraction)
AttrNumber *groupColIdx = NULL;
Path *cheapest_path;
Path *sorted_path;
+ bool use_hashed_grouping = false;
/* Preprocess targetlist in case we are inside an INSERT/UPDATE. */
tlist = preprocess_targetlist(tlist,
@@ -1210,6 +1211,29 @@ grouping_planner(Query *parse, double tuple_fraction)
sort_pathkeys = canonicalize_pathkeys(parse, sort_pathkeys);
/*
+ * Consider whether we might want to use hashed grouping.
+ */
+ if (parse->groupClause)
+ {
+ /*
+ * Executor doesn't support hashed aggregation with DISTINCT
+ * aggregates. (Doing so would imply storing *all* the input
+ * values in the hash table, which seems like a certain loser.)
+ */
+ if (parse->hasAggs &&
+ (contain_distinct_agg_clause((Node *) tlist) ||
+ contain_distinct_agg_clause(parse->havingQual)))
+ use_hashed_grouping = false;
+ else
+ {
+#if 0 /* much more to do here */
+ /* TEMPORARY HOTWIRE FOR TESTING */
+ use_hashed_grouping = true;
+#endif
+ }
+ }
+
+ /*
* Select the best path and create a plan to execute it.
*
* If no special sort order is wanted, or if the cheapest path is
@@ -1279,22 +1303,30 @@ grouping_planner(Query *parse, double tuple_fraction)
}
/*
- * If any aggregate is present, insert the Agg node, plus an explicit
- * sort if necessary.
+ * Insert AGG or GROUP node if needed, plus an explicit sort step
+ * if necessary.
*
* HAVING clause, if any, becomes qual of the Agg node
*/
- if (parse->hasAggs)
+ if (use_hashed_grouping)
{
+ /* Hashed aggregate plan --- no sort needed */
+ result_plan = (Plan *) make_agg(tlist,
+ (List *) parse->havingQual,
+ AGG_HASHED,
+ length(parse->groupClause),
+ groupColIdx,
+ result_plan);
+ /* Hashed aggregation produces randomly-ordered results */
+ current_pathkeys = NIL;
+ }
+ else if (parse->hasAggs)
+ {
+ /* Plain aggregate plan --- sort if needed */
AggStrategy aggstrategy;
if (parse->groupClause)
{
- aggstrategy = AGG_SORTED;
- /*
- * Add an explicit sort if we couldn't make the path come out
- * the way the AGG node needs it.
- */
if (!pathkeys_contained_in(group_pathkeys, current_pathkeys))
{
result_plan = make_groupsortplan(parse,
@@ -1303,9 +1335,18 @@ grouping_planner(Query *parse, double tuple_fraction)
result_plan);
current_pathkeys = group_pathkeys;
}
+ aggstrategy = AGG_SORTED;
+ /*
+ * The AGG node will not change the sort ordering of its
+ * groups, so current_pathkeys describes the result too.
+ */
}
else
+ {
aggstrategy = AGG_PLAIN;
+ /* Result will be only one row anyway; no sort order */
+ current_pathkeys = NIL;
+ }
result_plan = (Plan *) make_agg(tlist,
(List *) parse->havingQual,
@@ -1313,10 +1354,6 @@ grouping_planner(Query *parse, double tuple_fraction)
length(parse->groupClause),
groupColIdx,
result_plan);
- /*
- * Note: plain or grouped Agg does not affect any existing
- * sort order of the tuples
- */
}
else
{
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index ee037974769..f55c988bfc5 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.109 2002/09/11 14:48:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.110 2002/11/06 22:31:24 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -46,6 +46,7 @@ typedef struct
} check_subplans_for_ungrouped_vars_context;
static bool contain_agg_clause_walker(Node *node, void *context);
+static bool contain_distinct_agg_clause_walker(Node *node, void *context);
static bool pull_agg_clause_walker(Node *node, List **listptr);
static bool expression_returns_set_walker(Node *node, void *context);
static bool contain_subplans_walker(Node *node, void *context);
@@ -411,6 +412,32 @@ contain_agg_clause_walker(Node *node, void *context)
}
/*
+ * contain_distinct_agg_clause
+ * Recursively search for DISTINCT Aggref nodes within a clause.
+ *
+ * Returns true if any DISTINCT aggregate found.
+ */
+bool
+contain_distinct_agg_clause(Node *clause)
+{
+ return contain_distinct_agg_clause_walker(clause, NULL);
+}
+
+static bool
+contain_distinct_agg_clause_walker(Node *node, void *context)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Aggref))
+ {
+ if (((Aggref *) node)->aggdistinct)
+ return true; /* abort the tree traversal and return
+ * true */
+ }
+ return expression_tree_walker(node, contain_distinct_agg_clause_walker, context);
+}
+
+/*
* pull_agg_clause
* Recursively pulls all Aggref nodes from an expression tree.
*