summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/clauses.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-06-06 15:04:03 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-06-06 15:04:03 +0000
commite649796f128bd8702ba5744d36f4e8cb81f0b754 (patch)
tree050eda51ad8f0298731316ccf61db2c01a2863a3 /src/backend/optimizer/util/clauses.c
parent2c93861f7cef99b4613abd37ed7e4c15a95754b4 (diff)
downloadpostgresql-e649796f128bd8702ba5744d36f4e8cb81f0b754.tar.gz
Implement outer-level aggregates to conform to the SQL spec, with
extensions to support our historical behavior. An aggregate belongs to the closest query level of any of the variables in its argument, or the current query level if there are no variables (e.g., COUNT(*)). The implementation involves adding an agglevelsup field to Aggref, and treating outer aggregates like outer variables at planning time.
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r--src/backend/optimizer/util/clauses.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 0c2e652c79..3f4ced5a55 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.138 2003/05/28 22:32:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.139 2003/06/06 15:04:02 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -308,6 +308,13 @@ make_ands_implicit(Expr *clause)
* Recursively search for Aggref nodes within a clause.
*
* Returns true if any aggregate found.
+ *
+ * This does not descend into subqueries, and so should be used only after
+ * reduction of sublinks to subplans, or in contexts where it's known there
+ * are no subqueries. There mustn't be outer-aggregate references either.
+ *
+ * (If you want something like this but able to deal with subqueries,
+ * see rewriteManip.c's checkExprHasAggs().)
*/
bool
contain_agg_clause(Node *clause)
@@ -321,8 +328,12 @@ contain_agg_clause_walker(Node *node, void *context)
if (node == NULL)
return false;
if (IsA(node, Aggref))
+ {
+ Assert(((Aggref *) node)->agglevelsup == 0);
return true; /* abort the tree traversal and return
* true */
+ }
+ Assert(!IsA(node, SubLink));
return expression_tree_walker(node, contain_agg_clause_walker, context);
}
@@ -331,6 +342,10 @@ contain_agg_clause_walker(Node *node, void *context)
* Recursively search for DISTINCT Aggref nodes within a clause.
*
* Returns true if any DISTINCT aggregate found.
+ *
+ * This does not descend into subqueries, and so should be used only after
+ * reduction of sublinks to subplans, or in contexts where it's known there
+ * are no subqueries. There mustn't be outer-aggregate references either.
*/
bool
contain_distinct_agg_clause(Node *clause)
@@ -345,10 +360,12 @@ contain_distinct_agg_clause_walker(Node *node, void *context)
return false;
if (IsA(node, Aggref))
{
+ Assert(((Aggref *) node)->agglevelsup == 0);
if (((Aggref *) node)->aggdistinct)
return true; /* abort the tree traversal and return
* true */
}
+ Assert(!IsA(node, SubLink));
return expression_tree_walker(node, contain_distinct_agg_clause_walker, context);
}
@@ -357,6 +374,10 @@ contain_distinct_agg_clause_walker(Node *node, void *context)
* Recursively count the Aggref nodes in an expression tree.
*
* Note: this also checks for nested aggregates, which are an error.
+ *
+ * This does not descend into subqueries, and so should be used only after
+ * reduction of sublinks to subplans, or in contexts where it's known there
+ * are no subqueries. There mustn't be outer-aggregate references either.
*/
int
count_agg_clause(Node *clause)
@@ -374,6 +395,7 @@ count_agg_clause_walker(Node *node, int *count)
return false;
if (IsA(node, Aggref))
{
+ Assert(((Aggref *) node)->agglevelsup == 0);
(*count)++;
/*
@@ -388,6 +410,7 @@ count_agg_clause_walker(Node *node, int *count)
*/
return false;
}
+ Assert(!IsA(node, SubLink));
return expression_tree_walker(node, count_agg_clause_walker,
(void *) count);
}