aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-11-29 21:39:12 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-11-29 21:39:12 +0000
commitf68f11928d5c791873073c882775dae10283ff49 (patch)
tree628e4491fe33cdafb0e205d73e29b154ef68f94b /src/backend/optimizer/plan/planner.c
parent851a4c48fd468b15ef988d5d2c79a44246dd478d (diff)
downloadpostgresql-f68f11928d5c791873073c882775dae10283ff49.tar.gz
postgresql-f68f11928d5c791873073c882775dae10283ff49.zip
Tighten selection of equality and ordering operators for grouping
operations: make sure we use operators that are compatible, as determined by a mergejoin link in pg_operator. Also, add code to planner to ensure we don't try to use hashed grouping when the grouping operators aren't marked hashable.
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 2c1081f2677..0e5afccae3a 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.131 2002/11/26 03:01:58 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.132 2002/11/29 21:39:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,6 +17,7 @@
#include <limits.h>
+#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
@@ -36,9 +37,11 @@
#include "parser/analyze.h"
#include "parser/parsetree.h"
#include "parser/parse_expr.h"
+#include "parser/parse_oper.h"
#include "rewrite/rewriteManip.h"
#include "utils/lsyscache.h"
#include "utils/selfuncs.h"
+#include "utils/syscache.h"
/* Expression kind codes for preprocess_expression */
@@ -57,6 +60,7 @@ static Node *preprocess_expression(Query *parse, Node *expr, int kind);
static void preprocess_qual_conditions(Query *parse, Node *jtnode);
static Plan *inheritance_planner(Query *parse, List *inheritlist);
static Plan *grouping_planner(Query *parse, double tuple_fraction);
+static bool hash_safe_grouping(Query *parse);
static List *make_subplanTargetList(Query *parse, List *tlist,
AttrNumber **groupColIdx);
static Plan *make_groupsortplan(Query *parse,
@@ -1252,11 +1256,14 @@ grouping_planner(Query *parse, double tuple_fraction)
numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
/*
+ * Check can't-do-it conditions, including whether the grouping
+ * operators are hashjoinable.
+ *
* 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 (!enable_hashagg)
+ if (!enable_hashagg || !hash_safe_grouping(parse))
use_hashed_grouping = false;
else if (parse->hasAggs &&
(contain_distinct_agg_clause((Node *) tlist) ||
@@ -1554,6 +1561,33 @@ grouping_planner(Query *parse, double tuple_fraction)
return result_plan;
}
+/*
+ * hash_safe_grouping - are grouping operators hashable?
+ *
+ * We assume hashed aggregation will work if the datatype's equality operator
+ * is marked hashjoinable.
+ */
+static bool
+hash_safe_grouping(Query *parse)
+{
+ List *gl;
+
+ foreach(gl, parse->groupClause)
+ {
+ GroupClause *grpcl = (GroupClause *) lfirst(gl);
+ TargetEntry *tle = get_sortgroupclause_tle(grpcl, parse->targetList);
+ Operator optup;
+ bool oprcanhash;
+
+ optup = equality_oper(tle->resdom->restype, false);
+ oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash;
+ ReleaseSysCache(optup);
+ if (!oprcanhash)
+ return false;
+ }
+ return true;
+}
+
/*---------------
* make_subplanTargetList
* Generate appropriate target list when grouping is required.