aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/subselect.c32
-rw-r--r--src/test/regress/expected/aggregates.out10
-rw-r--r--src/test/regress/sql/aggregates.sql6
3 files changed, 46 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index a77cade1176..70a582533a8 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -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.100.2.5 2008/07/10 01:17:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.100.2.6 2009/04/25 16:45:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -446,13 +446,23 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
foreach(l, node->parParam)
{
PlannerParamItem *pitem = list_nth(PlannerParamList, lfirst_int(l));
+ Node *arg;
/*
* The Var or Aggref has already been adjusted to have the correct
* varlevelsup or agglevelsup. We probably don't even need to
* copy it again, but be safe.
*/
- args = lappend(args, copyObject(pitem->item));
+ arg = copyObject(pitem->item);
+
+ /*
+ * If it's an Aggref, its arguments might contain SubLinks,
+ * which have not yet been processed. Do that now.
+ */
+ if (IsA(arg, Aggref))
+ arg = SS_process_sublinks(arg, false);
+
+ args = lappend(args, arg);
}
node->args = args;
@@ -748,6 +758,12 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
* so after expanding its sublinks to subplans. And we don't want any steps
* in between, else those steps would never get applied to the aggregate
* argument expressions, either in the parent or the child level.
+ *
+ * Another fairly tricky thing going on here is the handling of SubLinks in
+ * the arguments of uplevel aggregates. Those are not touched inside the
+ * intermediate query level, either. Instead, SS_process_sublinks recurses
+ * on them after copying the Aggref expression into the parent plan level
+ * (this is actually taken care of in make_subplan).
*/
Node *
SS_replace_correlation_vars(Node *expr)
@@ -816,6 +832,18 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
}
/*
+ * Don't recurse into the arguments of an outer aggregate here.
+ * Any SubLinks in the arguments have to be dealt with at the outer
+ * query level; they'll be handled when make_subplan collects the
+ * Aggref into the arguments to be passed down to the current subplan.
+ */
+ if (IsA(node, Aggref))
+ {
+ if (((Aggref *) node)->agglevelsup > 0)
+ return node;
+ }
+
+ /*
* We should never see a SubPlan expression in the input (since this is
* the very routine that creates 'em to begin with). We shouldn't find
* ourselves invoked directly on a Query, either.
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 8aed1864034..6313b94770a 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -157,6 +157,16 @@ group by ten
having exists (select 1 from onek b
where sum(distinct a.four + b.four) = b.four);
ERROR: aggregates not allowed in WHERE clause
+-- Test handling of sublinks within outer-level aggregates.
+-- Per bug report from Daniel Grace.
+select
+ (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)))
+from tenk1 o;
+ ?column?
+----------
+ 9999
+(1 row)
+
--
-- test for bitwise integer aggregates
--
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index b6aba0d66b7..a79c4367e45 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -63,6 +63,12 @@ group by ten
having exists (select 1 from onek b
where sum(distinct a.four + b.four) = b.four);
+-- Test handling of sublinks within outer-level aggregates.
+-- Per bug report from Daniel Grace.
+select
+ (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)))
+from tenk1 o;
+
--
-- test for bitwise integer aggregates
--