]> granicus.if.org Git - postgresql/commitdiff
Recognize GROUPING() as a aggregate expression.
authorAndres Freund <andres@anarazel.de>
Sun, 26 Jul 2015 13:34:29 +0000 (15:34 +0200)
committerAndres Freund <andres@anarazel.de>
Sun, 26 Jul 2015 14:53:13 +0000 (16:53 +0200)
Previously GROUPING() was not recognized as a aggregate expression,
erroneously allowing the planner to move it from HAVING to WHERE.

Author: Jeevan Chalke
Reviewed-By: Andrew Gierth
Discussion: CAM2+6=WG9omG5rFOMAYBweJxmpTaapvVp5pCeMrE6BfpCwr4Og@mail.gmail.com
Backpatch: 9.5, where grouping sets were introduced

src/backend/optimizer/util/clauses.c
src/test/regress/expected/groupingsets.out
src/test/regress/sql/groupingsets.sql

index 0137e0ecfced21d4a5fa0fa6a6af92d3d87fcadc..c72dbef1c834431d8aaa18dbd71f7772e546104e 100644 (file)
@@ -390,7 +390,7 @@ make_ands_implicit(Expr *clause)
 
 /*
  * contain_agg_clause
- *       Recursively search for Aggref nodes within a clause.
+ *       Recursively search for Aggref/GroupingFunc nodes within a clause.
  *
  *       Returns true if any aggregate found.
  *
@@ -417,6 +417,11 @@ contain_agg_clause_walker(Node *node, void *context)
                Assert(((Aggref *) node)->agglevelsup == 0);
                return true;                    /* abort the tree traversal and return true */
        }
+       if (IsA(node, GroupingFunc))
+       {
+               Assert(((GroupingFunc *) 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);
 }
index 2e12a53d69fd6914a2ff513a0df2a59ebba36c52..bdd77f8979c723ce07b436613da5b9c2ccd850ec 100644 (file)
@@ -486,6 +486,68 @@ having exists (select 1 from onek b where sum(distinct a.four) = b.four);
    9 |   3
 (25 rows)
 
+-- HAVING with GROUPING queries
+select ten, grouping(ten) from onek
+group by grouping sets(ten) having grouping(ten) >= 0
+order by 2,1;
+ ten | grouping 
+-----+----------
+   0 |        0
+   1 |        0
+   2 |        0
+   3 |        0
+   4 |        0
+   5 |        0
+   6 |        0
+   7 |        0
+   8 |        0
+   9 |        0
+(10 rows)
+
+select ten, grouping(ten) from onek
+group by grouping sets(ten, four) having grouping(ten) > 0
+order by 2,1;
+ ten | grouping 
+-----+----------
+     |        1
+     |        1
+     |        1
+     |        1
+(4 rows)
+
+select ten, grouping(ten) from onek
+group by rollup(ten) having grouping(ten) > 0
+order by 2,1;
+ ten | grouping 
+-----+----------
+     |        1
+(1 row)
+
+select ten, grouping(ten) from onek
+group by cube(ten) having grouping(ten) > 0
+order by 2,1;
+ ten | grouping 
+-----+----------
+     |        1
+(1 row)
+
+select ten, grouping(ten) from onek
+group by (ten) having grouping(ten) >= 0
+order by 2,1;
+ ten | grouping 
+-----+----------
+   0 |        0
+   1 |        0
+   2 |        0
+   3 |        0
+   4 |        0
+   5 |        0
+   6 |        0
+   7 |        0
+   8 |        0
+   9 |        0
+(10 rows)
+
 -- FILTER queries
 select ten, sum(distinct four) filter (where four::text ~ '123') from onek a
 group by rollup(ten);
index eeea995f337a279fd32330f9d318e62950e5b431..8eb580812a9ef853ef7469684665db9fb2da3c7e 100644 (file)
@@ -154,6 +154,23 @@ select ten, sum(distinct four) from onek a
 group by grouping sets((ten,four),(ten))
 having exists (select 1 from onek b where sum(distinct a.four) = b.four);
 
+-- HAVING with GROUPING queries
+select ten, grouping(ten) from onek
+group by grouping sets(ten) having grouping(ten) >= 0
+order by 2,1;
+select ten, grouping(ten) from onek
+group by grouping sets(ten, four) having grouping(ten) > 0
+order by 2,1;
+select ten, grouping(ten) from onek
+group by rollup(ten) having grouping(ten) > 0
+order by 2,1;
+select ten, grouping(ten) from onek
+group by cube(ten) having grouping(ten) > 0
+order by 2,1;
+select ten, grouping(ten) from onek
+group by (ten) having grouping(ten) >= 0
+order by 2,1;
+
 -- FILTER queries
 select ten, sum(distinct four) filter (where four::text ~ '123') from onek a
 group by rollup(ten);