Repository: kayak/pypika
Pull request #99 (2018-01-29 10:20:03)

Changed rollup to combine additional rollup fields
Changed the behavior of rollup to combine subsequent rollup fields after a rollup has been added to the group by clause

coveralls: 
[![Coverage Status](https://coveralls.io/builds/15264927/badge)](https://coveralls.io/builds/15264927)

Coverage increased (+0.003%) to 98.346% when pulling **b4271975352b78f54558f03156b447367b354872 on combine_rollup** into **48366fd04a2d56e1df6511aab508d4287568d468 on master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/15264927/badge)](https://coveralls.io/builds/15264927)

Coverage increased (+0.003%) to 98.346% when pulling **b4271975352b78f54558f03156b447367b354872 on combine_rollup** into **48366fd04a2d56e1df6511aab508d4287568d468 on master**.


Patch:
diff --git a/pypika/queries.py b/pypika/queries.py
index 1a81008..3ce9b02 100644
--- a/pypika/queries.py
+++ b/pypika/queries.py
@@ -359,6 +359,7 @@ class QueryBuilder(Selectable, Term):
                  for term in terms]
 
         if for_mysql:
+            # MySQL rolls up all of the dimensions always
             if not terms and not self._groupbys:
                 raise RollupException('At least one group is required. Call Query.groupby(term) or pass'
                                       'as parameter to rollup.')
@@ -366,6 +367,10 @@ class QueryBuilder(Selectable, Term):
             self._mysql_rollup = True
             self._groupbys += terms
 
+        elif 0 < len(self._groupbys) and isinstance(self._groupbys[-1], Rollup):
+            # If a rollup was added last, then append the new terms to the previous rollup
+            self._groupbys[-1].args += terms
+
         else:
             self._groupbys.append(Rollup(*terms))
 


Test patch:
diff --git a/pypika/tests/test_groupby_modifiers.py b/pypika/tests/test_groupby_modifiers.py
index 14a675a..5963cd4 100644
--- a/pypika/tests/test_groupby_modifiers.py
+++ b/pypika/tests/test_groupby_modifiers.py
@@ -41,7 +41,7 @@ class RollupTests(unittest.TestCase):
                 fn.Sum(self.table.bar)
             ).rollup(vendor='mysql')
 
-    def test_no_rollup_after_rollup(self):
+    def test_no_rollup_after_rollup_mysql(self):
         with self.assertRaises(AttributeError):
             Query.from_(self.table).select(
                 self.table.foo,
@@ -141,7 +141,7 @@ class RollupTests(unittest.TestCase):
             self.table.fiz,
         )
 
-        self.assertEqual('SELECT "foo","fiz",SUM("bar") FROM "abc" GROUP BY ROLLUP("foo"),ROLLUP("fiz")', str(q))
+        self.assertEqual('SELECT "foo","fiz",SUM("bar") FROM "abc" GROUP BY ROLLUP("foo","fiz")', str(q))
 
     def test_verticaoracle_rollups_with_parity(self):
         q = Query.from_(self.table).select(
@@ -152,3 +152,14 @@ class RollupTests(unittest.TestCase):
         )
 
         self.assertEqual('SELECT "buz" FROM "abc" GROUP BY ROLLUP(("foo","bar"),"fiz")', str(q))
+
+    def test_verticaoracle_rollups_with_multiple_rollups_and_parity(self):
+        q = Query.from_(self.table).select(
+            self.table.buz,
+        ).rollup(
+            [self.table.foo, self.table.bar],
+        ).rollup(
+            [self.table.fiz, self.table.buz],
+        )
+
+        self.assertEqual('SELECT "buz" FROM "abc" GROUP BY ROLLUP(("foo","bar"),("fiz","buz"))', str(q))